Laravel 雄辩用 whereHas 或其他限制 withCount

Posted

技术标签:

【中文标题】Laravel 雄辩用 whereHas 或其他限制 withCount【英文标题】:Laravel eloquent restrict withCount with whereHas or another 【发布时间】:2021-12-24 22:58:38 【问题描述】:

我有 3 个模型 SupplierPurchasePurchaseDetail。 为了通过 Purchase 将 Supplier 模型与 PurchaseDetail 加入,我创建了一个 hasManyThrough 关系。

hasManyThroughSupplier 模型:

public function detail_purchases()
    return $this->hasManyThrough(PurchaseDetail::class, Purchase::class);

关系很好,我可以计算从卖家那里购买的数量如下:

$collectors = Supplier::withCount(['detail_purchases as qty_sold' => function($query) 
    return $query->select(\DB::raw('SUM(qty)'))
        ->where('unit', '=', 'kg');
])
    ->where('supplier_type','=','persona_natural')
    ->orderBy('qty_sold','desc')
    ->get();

SQL 查询输出:

select `suppliers`.*, (
    select SUM(qty)
    from `purchase_details`
    inner join `purchases` on `purchases`.`id` = `purchase_details`.`purchase_id`
    where `suppliers`.`id` = `purchases`.`supplier_id`
        and `unit` = 'kg'
        and `purchases`.`deleted_at` is null
) as `qty_sold`
from `suppliers`
where `supplier_type` = 'persona_natural'
order by `qty_sold` desc;

输出行:

我的问题是,这个查询给我带来了我没有从他们那里购买过的卖家,我不知道如果假设 hasManyThrough 关系只加入那些在 Purchase 中注册或制作的人,他们为什么会渗透到查询中从他们那里购买。

Supplier 模型还有另一个称为purchases 的关系:

public function purchases() 
    return $this->hasMany(Purchase::class, 'supplier_id');

并且模型Purchase 与 PurchaseDetail 有关系 hasMany :

public function details()
    return $this->hasMany(PurchaseDetail::class, 'purchase_id');

更新

使用 whereHas now 我可以获取我购买的所有供应商,但是 qty_sold 没有出现在结果中:

$collectors =  Supplier::whereHas('purchases', function($query)
    $query->withCount(['details as qty_sold' => function($query)
        $query->select(\DB::raw('SUM(qty)'))
            ->where('unit', '=', $this->unit);
        ]);
    )
    ->where('supplier_type','=','persona_natural')
    ->get();

此选择很重要,因为我想知道我购买的所有产品中有多少 kgs

【问题讨论】:

通过将->get() 替换为->toSql() 来获取执行的SQL 查询,并将结果发布到您的问题中。这可能有助于理解为什么要包括其他供应商。 嗨@Tony 我已经更新了我的问题,检查它..这是扔掉所有供应商.. @Tony 我已经更新了,看看就完事了。 whereHas 有效,但 SUM 未出现在结果中。 在您更新的查询中,您可以将withCount 移出子查询吗?所以你会得到Supplier::withCount(...)->whereHas('purchases')... 在尝试构建更复杂的查询时,我做的另一件事是用 SQL 将其写出来,然后开始将其转换为 PDO 查询,然后再转换为 Eloquent。它还有助于逐位构建查询:从检索正确的行开始,然后进行聚合。 查看您的第一个查询,它选择了所有供应商,然后执行子查询以获取计数,因为使用您的 hasManyThrough 表连接的表仅在子查询中。 【参考方案1】:

谢谢@托尼

在您更新的查询中,您可以将 withCount 移出子查询吗?所以你会有 Supplier::withCount(...)->whereHas('purchases')..

好的,我修复了它,首先添加 whereHas 指令,然后我使用了 hasManyThroughwithCount 的关系。通过这种方式,只有购买过的供应商才是选择。

 $collectors = Supplier::whereHas('purchases')
                       ->withCount([
                           'detail_purchases as qty_sold' => function($query)
                               $query->select(\DB::raw('SUM(qty)'))
                                     ->where('unit', '=', 'kg');
                           
                        ])
                        ->where('supplier_type','=', 'persona_natural')
                        ->get();

【讨论】:

很高兴听到你成功了

以上是关于Laravel 雄辩用 whereHas 或其他限制 withCount的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 雄辩与条件

SQLSTATE[HY000] [2002] 使用 whereHas 时 laravel 中的连接被拒绝错误

雄辩的查询构建器laravel 5.6中的未知列

雄辩的多个 whereHas('pivot_table_X') AND whereHas('pivot_table_X')

Laravel - whereHas() 中关系的最新记录

(Laravel) 使用“雄辩的关系”连接 3 个或更多表