首页 文章

约束渴望加载的关系

提问于
浏览
0

我发现 with 函数的一个非常奇怪的行为,用于重载关系 . 我有 ProductDeal 关系,例如 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() 返回一个空集合,正如您所期望的那样 .

我最初发现这个问题,同时试图与 DealImage 关系一起取出五个随机产品:

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

  • 1

    你对这个概念的理解是完全错误的 .

    如果你说的是 Product belongsTo() Deal ,那么我们假设 Deal hasMany() Products .

    这是交易表

    deals
    id | name | ends_at | blah | blah
    
    products
    id | deal_id | name | blah | blah
    

    所以基本上, 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() ,你必须这样做 .

    Deal::with('product')->where('ends_at', '>', Carbon::now()->toDateTimeString())
    
  • 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();
    

相关问题