我发现了with
函数对于重载关系的一种非常奇怪的行为。我有Product
和Deal
个关系,例如Product
belongsTo()
Deal
(通过product_id
表格中的deals
。现在,当我尝试销售所有产品时:
Product::with(['deal' => function($query) {
$query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
}])->get()
这会返回所有产品的集合,即使deals
表中有无记录且所有产品都有{ {1}}设置为deal_id
。同时,NULL
会返回一个空集合,正如您所期望的那样。
我最初在尝试与Product::has('deal')->get()
和Deal
关系一起提取五种随机商品时发现了这个问题:
Image
这会产生一个在所有Product::with(['deal' => function ($query) {
$query->whereDate('ends_at', '>', // promo still active
Carbon::now()->toDateTimeString());
},
'images' => function ($query) {
$query->where('featured', true); // image featured on homepage
}])
->where('status', 'IN_STOCK') // 'In Stock'
->whereNull('deleted_at') // wasn't soft-deleted
->orderByRaw('RAND()')
->take(5)->get())
中有5个随机Product
的集合。我尝试使用Product
,但结果相同。
我在这里做错了什么?
答案 0 :(得分:1)
你对这个概念的理解是完全错误的。
如果您说的是产品 hasMany()
交易,那么我们假设交易 deals
id | name | ends_at | blah | blah
products
id | deal_id | name | blah | blah
<强>产品强>
这是交易表
Product::with('deal')
所以基本上,Deal::with('products')
应该返回所有产品,其特惠是Eager。但是deal_id
会返回一个空集合,因为没有产品中包含有效的belongTo
。
重要的是要注意,由于产品只能Product::with('deal')
一个交易,所以当您使用时,您将始终获得交易模型而不是集合执行Deal::with('products')
查询。但是当你执行ends_at > Carbon::now()
时,你一定会得到一个集合。
所以基本上,当你说
时这将返回所有产品的集合,即使交易表中没有记录,并且所有产品的deal_id都设置为NULL。
非常明显 ....因为这里的查询是在产品而不是交易上完成的。如果您要在Deal::with('product')->where('ends_at', '>', Carbon::now()->toDateTimeString())
找到交易,则必须执行此操作。
{{1}}
答案 1 :(得分:0)
当你使用with
时,它只会急切加载所提供约束的关系,但是如果你想通过他们的关系过滤父模型,那么whereHas
就是你的朋友。所以你的查询应该是:
Product::whereHas('deal' => function($query) {
$query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
})->get();
现在它只会获取满足给定约束条件的Product
。
您还可以将with
和whereHas
的组合用作:
Product::whereHas('deal' => function($query) {
$query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
})
->with(['deal' => function($query) {
$query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
}])
->get();