我发现这些方法背后的概念和意义有点令人困惑,有人能在一个例子中(如果可能的话)向我解释一下has和with is之间的区别吗?
With
With()用于快速加载。这基本上意味着,沿着主模型,Laravel将预加载您指定的关系。如果您有一个模型集合,并且希望为所有模型加载一个关系,那么这将特别有用。因为使用即时加载,您只运行一个额外的DB查询,而不是对集合中的每个模型运行一个查询。
例子:
用户> 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()是根据关系筛选选择模型。所以它的作用和正常的WHERE条件非常相似。如果您只使用has('relation'),这意味着您只想获得在此关系中至少有一个相关模型的模型。
例子:
用户> hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
WhereHas
whereHas()的工作原理与has()基本相同,但允许您为相关模型指定额外的过滤器进行检查。
例子:
用户> 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
文档已经解释了其用法,因此我将使用SQL来解释这些方法。
例子:
假设有一个Order (orders)有许多OrderItem (order_items),并且你已经建立了它们之间的关系:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
这三种方法都基于一种关系。
with
Result: with()返回模型对象及其相关结果。
优点:急装,防止N+1问题。
当你使用以下雄辩的建设者:
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的外键结果合并,最终返回集合结果。
所以如果你在闭包中选择了没有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
当模型对象的关系不为空时,Has将返回模型对象。
Order::has('orderItems')->get();
Laravel将此代码更改为一个SQL查询:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
whereHas
方法whereHas和orWhereHas在你的has查询上放置where条件。这些方法允许您向关系约束中添加自定义约束。
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel将此代码更改为一个SQL查询:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
推荐文章
- SQLAlchemy:引擎、连接和会话差异
- Laravel:获取基本URL
- 迁移:不能添加外键约束
- Visual Studio代码PHP Intelephense保持显示不必要的错误
- 如何在laravel雄辩中选择具体的栏目
- Django查询- id vs pk
- PSR-0和PSR-4有什么区别?
- 在Laravel安全地移除迁移
- 联接顺序在SQL中重要吗?
- Laravel 4:如何使用雄辩的ORM进行“排序”
- Hibernate抛出org.hibernate.AnnotationException:没有为entity指定标识符:com..domain.idea.MAE_MFEView
- 好的PHP ORM库?
- 禁用Laravel的雄辩时间戳
- 如何在PATH中放置~/.composer/vendor/bin目录?
- 如何修复org.hibernate.LazyInitializationException -不能初始化代理-没有会话