Laravel - Eloquent "Has", "With", "WhereHas" - 它们是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30231862/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 17:00:37  来源:igfitidea点击:

Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean?

laravelormeloquentrelational-databaserelationship

提问by lukasgeiter

I've found the concept and meaning behind these methods to be a little confusing, is it possible for somebody to explain to me what the difference between hasand withis, in the context of an example (if possible)?

我发现这些方法背后的概念和含义有点令人困惑,是否有人可以在示例的上下文中向我解释has和之间的区别with(如果可能)?

回答by lukasgeiter

With

with()is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.

with()用于急切加载。这基本上意味着,沿着主模型,Laravel 将预加载您指定的关系。如果您有一组模型并且想要为所有模型加载关系,这将特别有用。因为使用预先加载,您只会运行一个额外的数据库查询,而不是为集合中的每个模型运行一个。

Example:

例子:

User > hasMany > Post

User > hasMany > Post

$users = User::with('posts')->get();
foreach($users as $user){
    $users->posts; // posts is already loaded and no additional DB query is run
}

Has

has()is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation')that means you only want to get the models that have at least one related model in this relation.

has()是根据关系过滤选择模型。所以它的行为与正常的 WHERE 条件非常相似。如果您只是使用has('relation')这意味着您只想获得在此关系中至少有一个相关模型的模型。

Example:

例子:

User > hasMany > Post

User > hasMany > Post

$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection

WhereHas

哪里有

whereHas()works basically the same as has()but allows you to specify additional filters for the related model to check.

whereHas()工作原理基本相同,has()但允许您为相关模型指定额外的过滤器进行检查。

Example:

例子:

User > hasMany > Post

User > hasMany > Post

$users = User::whereHas('posts', function($q){
    $q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned

回答by TsaiKoga

Documenthas already explain the usage. So I am using SQL to explain these methods

文档已经说明了用法。所以我用SQL来解释这些方法

Example:

例子:



Assuming there is an Order (orders)has many OrderItem (order_items).

假设有一个Order (orders)has many OrderItem (order_items)

And you have already build the relationship between them.

而你已经建立了他们之间的关系。

// App\Models\Order:
public function orderItems() {
    return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}

These three methods are all based on a relationship.

这三种方法都是基于一种关系

With



Result:with()return the model object and its related results.

结果:with()返回模型对象及其相关结果。

Advantage:It is eager-loadingwhich can prevent the N+1 problem.

优点:eager-loading,可以防止N+1问题

When you are using the following Eloquent Builder:

当您使用以下 Eloquent Builder 时:

Order::with('orderItems')->get();

Laravel change this code to only two SQL:

Laravel 将此代码更改为只有两个 SQL

// get all orders:
SELECT * FROM orders; 

// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);

And then laravel merge the results of the second SQLas different from the results of the first SQLby foreign key. At last return the collection results.

然后laravel通过外键合并第二条SQL的结果与第一条SQL的结果不同。最后返回收集结果。

So if you selected columns without the foreign_key in closure, the relationship result will be empty:

因此,如果您选择了闭包中没有外键的列,则关系结果将为空:

Order::with(['orderItems' => function($query) { 
           // $query->sum('quantity');
           $query->select('quantity'); // without `order_id`
       }
])->get();

#=> result:
[{  id: 1,
    code: '00001',
    orderItems: [],    // <== is empty
  },{
    id: 2,
    code: '00002',
    orderItems: [],    // <== is empty
  }...
}]

Has



Haswill return the model's object that its relationship is not empty.

Has将返回其关系不为空的模型对象。

Order::has('orderItems')->get();

Laravel change this code to one SQL:

Laravel 将此代码更改为一个 SQL

select * from `orders` where exists (
    select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)

whereHas

哪里有



whereHasand orWhereHasmethods to put whereconditions on your hasqueries. These methods allow you to add customized constraints to a relationship constraint.

whereHas以及对查询orWhereHas设置where条件的方法has。这些方法允许您向关系约束添加自定义约束

Order::whereHas('orderItems', function($query) {
   $query->where('status', 1);
})->get();

Laravel change this code to one SQL:

Laravel 将此代码更改为一个 SQL

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)