Eloqent имеет много отношений с условием

У меня есть модельный контракт со свойствами 'id', 'orderer_user_id' и 'contractor_user_id'. У меня есть подпись модели со свойствами 'contract_id', 'user_id' и 'подписано'. У меня есть отношение hasMany к договору, чтобы получить подписи, принадлежащие договору. Каждый контракт имеет две подписи, одна принадлежит заказчику, а другая подрядчику.

Мне нужно получить все контракты, подписи которых у заказчиков еще не подписаны (поэтому "contract_id" должен быть идентификатором его родителя, "user_id" должен быть "orderer_user_id" его родителя, а "подписанный" должен быть ложным)

Что такое Laravel/Eloquent для этого? Я понимаю, что могу просто кодировать цикл foreach и повторять все контракты, проверять его подписи, а затем создавать коллекцию контрактов с неподписанными подписями заказчика, но это кажется неуклюжим. Я играл с отношениями / имеет / не имеет и т.д., но я не могу получить правильные результаты.

2 ответа

Вы должны иметь отношение, реализованное по модели контракта.

// Contract.php

public function signatures() {
    // add proper parameters 2nd: foreign key and 3rd: local key if 
    // your Database design is not respecting laravel/eloquent naming guidelines
    return $this->hasMany(Signature::class); 
}

Для получения неподписанных контрактов это должно работать:

$unsignedContracts = Contract::whereHas("signatures", '<', 2)->get();    

Я думаю, что это также не должно охватывать записи вообще, но если это не так, вы также можете попробовать это

$unsignedContracts = Contract::whereDoesntHave("signatures")
                             ->orWhereHas("signatures", '<', 2)->get();

Если вы хотите запросить все подписи с дополнительным условием, это также возможно:

$unsignedContracts = Contract::whereHas("signatures", function($q) {
                         $q->where("signed","=",false);
                     })->get()

Вы также можете ввести конкретные отношения для подрядчика и заказчика в модели подписи:

// Signature.php

public function contractor() {
    return $this->belongsTo(User::class, "contractor_user_id", "id"); 
}

public function orderer() {
    return $this->belongsTo(User::class, "orderer_user_id", "id"); 
}

С этим вы должны быть в состоянии сделать это:

// this should return all contracts where one of the 
// required users has not signed yet
$unsignedContracts = Contract::where(function($q) {
    $q->whereDoesntHave("contractor")
      ->orWhereDoesntHave("orderer");
})->get();

Документация по Laravel довольно хорошая imho, посмотрите на
https://laravel.com/docs/5.6/eloquent-relationships для получения дополнительной информации.

Вы можете либо создать справку, либо определить в своих множественных отношениях, какими вы хотите быть, когда бы вы их ни называли (добавьте ->, где ()-> выберите ()...).

Лично я бы создал область видимости, чтобы вы могли просто вызывать отношения, когда захотите, и просто применять области видимости, когда это необходимо, чтобы обе функции (в конечном итоге, функции) были независимыми.

https://laravel.com/docs/5.6/eloquent

Другие вопросы по тегам