我发现 with
函数的一个非常奇怪的行为,用于重载关系 . 我有 Product
和 Deal
关系,例如 Product
belongsTo()
Deal
(通过 deals
表中的 product_id
) . 现在,当我尝试销售所有产品时:
Product::with(['deal' => function($query) {
$query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
}])->get()
这将返回 all 产品的集合,即使 deals
表中有 no 条记录且 all 产品 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())
这产生了一个集合,在所有 Product
中有5个随机 Product
. 我尝试了 query->whereNotNull('ends_at')->whereDate('ends_at' ..... );
但得到了相同的结果 .
我在这做错了什么?
2 回答
你对这个概念的理解是完全错误的 .
如果你说的是 Product
belongsTo()
Deal ,那么我们假设 DealhasMany()
Products .这是交易表
所以基本上,
Product::with('deal')
应该返回所有产品,其特卖是Eager . 但Deal::with('products')
会返回一个空集合,因为没有产品中有有效的deal_id
.重要的是要注意,因为 Product 只能 Deal 单个 Deal ,所以当您执行
Product::with('deal')
查询时,您将始终获得交易模型而不是集合 . 但是当你执行Deal::with('products')
时,你一定会得到一个集合 .所以基本上,当你说
这将返回所有产品的集合,即使交易表中没有记录,并且所有产品的deal_id都设置为NULL .
It is pretty obvious ....因为这里的查询是在产品而不是交易上完成的 . 如果你想找到 Deal 哪里
ends_at > Carbon::now()
,你必须这样做 .当你使用
with
时,它只会急切加载所提供约束的关系,但是如果你想按照它们的关系过滤父模型,那么whereHas
就是你的朋友 . 所以你的查询应该是:现在它只会获取满足给定约束的那些
Product
.您还可以使用
with
和whereHas
的组合: