Laravel - Eloquent "Has", "With", "WhereHas" - 它们是什么意思?
Laravel - Eloquent "Has", "With", "WhereHas" - What do they mean?
我发现这些方法背后的概念和含义有点混乱,有人可以向我解释一下 has
和 with
之间的区别吗?示例的上下文(如果可能)?
有
with()
用于 预先加载 。这基本上意味着,沿着主模型,Laravel 将预加载您指定的关系。如果您有一组模型并且想要为所有模型加载关系,这将特别有用。因为使用预先加载,您 运行 只需一个额外的数据库查询,而不是对集合中的每个模型进行一个查询。
示例:
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()
是根据关系筛选选择模型。所以它的行为与普通的 WHERE 条件非常相似。如果你只使用 has('relation')
那意味着你只想得到至少有一个相关模型在这个关系中的模型。
示例:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
哪里有
whereHas()
与 has()
的工作原理基本相同,但允许您为要检查的相关模型指定额外的过滤器。
示例:
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
documentation已经说明了用法,所以我就用SQL来说明方法。
示例:
假设有一个 Order (orders)
有很多 OrderItem (order_items)
并且您已经建立了它们之间的关系:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
这三种方法都是基于一种关系。
与
结果: with()
return模型对象及其相关结果。
优点:eager-loading可以防止N+1问题 .
当您使用以下 Eloquent 生成器时:
Order::with('orderItems')->get();
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...);
然后 Laravel 合并 第二个 SQL 查询的结果 与 第一个 SQL 的结果 通过 外键 ,最终 return 收集结果。
因此,如果您在闭包中选择了没有 foreign_key 的列,关系结果将为空:
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
将 return 当 关系不为空时 return 模型的对象 .
Order::has('orderItems')->get();
Laravel 将此代码更改为 one SQL query:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
哪里有
方法 whereHas
和 orWhereHas
为您的 has
查询设置了 where
条件。这些方法允许您将自定义约束添加到关系约束。
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel 将此代码更改为 one SQL query:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
我发现这些方法背后的概念和含义有点混乱,有人可以向我解释一下 has
和 with
之间的区别吗?示例的上下文(如果可能)?
有
with()
用于 预先加载 。这基本上意味着,沿着主模型,Laravel 将预加载您指定的关系。如果您有一组模型并且想要为所有模型加载关系,这将特别有用。因为使用预先加载,您 运行 只需一个额外的数据库查询,而不是对集合中的每个模型进行一个查询。
示例:
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()
是根据关系筛选选择模型。所以它的行为与普通的 WHERE 条件非常相似。如果你只使用 has('relation')
那意味着你只想得到至少有一个相关模型在这个关系中的模型。
示例:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
哪里有
whereHas()
与 has()
的工作原理基本相同,但允许您为要检查的相关模型指定额外的过滤器。
示例:
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
documentation已经说明了用法,所以我就用SQL来说明方法。
示例:
假设有一个 Order (orders)
有很多 OrderItem (order_items)
并且您已经建立了它们之间的关系:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
这三种方法都是基于一种关系。
与
结果: with()
return模型对象及其相关结果。
优点:eager-loading可以防止N+1问题 .
当您使用以下 Eloquent 生成器时:
Order::with('orderItems')->get();
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...);
然后 Laravel 合并 第二个 SQL 查询的结果 与 第一个 SQL 的结果 通过 外键 ,最终 return 收集结果。
因此,如果您在闭包中选择了没有 foreign_key 的列,关系结果将为空:
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
将 return 当 关系不为空时 return 模型的对象 .
Order::has('orderItems')->get();
Laravel 将此代码更改为 one SQL query:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
哪里有
方法 whereHas
和 orWhereHas
为您的 has
查询设置了 where
条件。这些方法允许您将自定义约束添加到关系约束。
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel 将此代码更改为 one SQL query:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)