约束渴望加载的关系

时间:2016-12-17 22:16:03

标签: laravel eloquent laravel-5.3

我发现了with函数对于重载关系的一种非常奇怪的行为。我有ProductDeal个关系,例如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,但结果相同。

我在这里做错了什么?

2 个答案:

答案 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

您还可以将withwhereHas的组合用作:

Product::whereHas('deal' => function($query) {
          $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
        })
        ->with(['deal' => function($query) {
            $query->whereDate('ends_at', '>', Carbon::now()->toDateTimeString());
        }])
        ->get();