简体   繁体   English

Eloquent与条件有很多关系

[英]Eloquent hasMany relationship with condition

I have a model Contract with properties 'id', 'orderer_user_id' and 'contractor_user_id'.我有一个带有属性“id”、“orderer_user_id”和“contractor_user_id”的模型合同。 I have a model Signature with properties 'contract_id', 'user_id' and 'signed'.我有一个带有属性“contract_id”、“user_id”和“signed”的模型签名。 I have a hasMany relationship on Contract to retrieve the Signatures belonging to the contract.我在合同上有一个 hasMany 关系来检索属于合同的签名。 Each Contract has two Signatures, one belonging to the orderer, the other to the contractor.每个合同有两个签名,一个属于订购者,另一个属于承包商。

I need to get all Contracts that have its orderer signatures not yet signed (so 'contract_id' has to be the id of its parent, 'user_id' has to be the 'orderer_user_id' of its parent and 'signed' has to be false)我需要获取所有尚未签署订购者签名的合同(因此“contract_id”必须是其父代的 ID,“user_id”必须是其父代的“orderer_user_id”并且“signed”必须是假的)

What's the Laravel/Eloquent way to achieve this?实现这一目标的 Laravel/Eloquent 方法是什么? I understand I can just code a foreach loop and iterate all contracts, check its signatures and then build a collection of contracts with unsigned orderer signatures but it feels clumsy.我知道我可以编写一个 foreach 循环并迭代所有合同,检查其签名,然后使用未签名的订购者签名构建一组合同,但感觉很笨拙。 I've been playing around with relationships/has/doesnthave etc. but I can't seem to get the correct results.我一直在玩弄关系/有/没有等,但我似乎无法得到正确的结果。

You should have the relation implemented on Contract model您应该在 Contract 模型上实现关系

// 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); 
}

In order to retrieve the unsigned Contracts this should work:为了检索未签名的合同,这应该有效:

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

I think this should also cover no entries at all, but in case it does not, you can also try this我认为这也应该根本不包括任何条目,但如果没有,您也可以尝试这个

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

If you want to query all signatures with an additional condition this is also possible:如果您想使用附加条件查询所有签名,这也是可能的:

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

You can also introduce concrete relations for contractor and orderer in the Signature model:您还可以在 Signature 模型中引入承包商和订购者的具体关系:

// 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"); 
}

With these you should be able to do this:有了这些,你应该能够做到这一点:

// 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 documentation is pretty nice imho, have a look on Laravel 文档非常好,恕我直言,看看
https://laravel.com/docs/5.6/eloquent-relationships#querying-relations for more input. https://laravel.com/docs/5.6/eloquent-relationships#querying-relations获取更多输入。

You can either create a cope or define on your multiple relationship what you wish to be whenever you call it (add a ->where()->select()...).无论何时调用它,您都可以创建一个对应或定义您希望成为的对象(添加 ->where()->select()...)。

Personally, I'd make a scope so you can just call the relationship whenever you want and just apply scopes whenever needed, making both functions (that's what they are in the end, functions) to be independent.就我个人而言,我会创建一个作用域,这样您就可以随时调用关系,并在需要时应用作用域,使两个函数(这就是它们最终的功能)独立。

https://laravel.com/docs/5.6/eloquent#local-scopes https://laravel.com/docs/5.6/eloquent#local-scopes

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM