首页 > 解决方案 > 如何使用 eloquent 通过具有嵌套关系(belongsToMany)的子类别计算父类别中的产品

问题描述

我正在尝试计算父类别中的所有有效产品。一个父类有很多子类(只有一层深)。一个产品可以分配给多个子类别,但不能分配给父类别。

例如。我有“玩具”(父母)类别,有 3 个子类别“男孩”(有 5 个产品)、“女孩”(有 6 个产品)、“青少年”(有 12 个产品)。

我在主页的侧边栏菜单包含所有父类别,并希望使用雄辩的方式显示各个父类别的产品数量。雄辩的查询正在视图作曲家中使用。

使用上面的示例,我想显示如下:

Toys  23 (5 + 6 + 12 = 23 after totaling products from child categories)  

Games 10

Sports 15

and so on..

我想获取包含产品数量的父类别,而不是子类别详细信息。

我的 Category.php 模型

public function parent() {
    return $this->belongsTo(self::class, 'parent_id');
}

public function children() {
    return $this->hasMany(self::class, 'parent_id', 'id');
}

public function products() {
    return $this->belongsToMany('App\Product');
}

我的 Product.php 模型

public function categories() {
    return $this->belongsToMany('App\Category');
}

public function user() {
    return $this->belongsTo('App\User');
}

我尝试过的查询

Category::select('id', 'parent_id', 'slug' ,'name')->where(['active' => 1, 'parent_id' => null])->with(['children' => function($query) {
        $query->withCount('products');
    }])->get();

这给了我孩子的产品数量。我可以遍历孩子,并可以为父母添加总产品。但是,这似乎不是一个好方法,因为这也会加载我不需要的子类别数据。我总共有大约 400 个类别。

Category::select('id', 'parent_id', 'slug' ,'name')->where(['active' => 1, 'parent_id' => null])->with('children')->withCount('products')->get();

这使产品计数为 0,显然是因为父类别没有分配给它的产品。

我看到很多她使用 withCount 的例子,但它们都解释了 hasManyThrough 关系。我在类别和产品模型中设置了 belongsToMany 关系。如果 withCount 在任何地方的 belongsToMany 关系中实现,请指导我。

我正在寻找优化的数据库查询以获得我需要的结果。请让我知道你的想法。

非常感谢您宝贵的时间。

标签: phpmysqllaraveleloquent

解决方案


如果我正确理解您的问题,您可以通过向类别模型添加方法来实现这一点。像这样

// Category.php
public function getProductCountAttribute()
{
    return Product::whereIn(
        'category_id',
        Category::where('parent_id', $this->getKey())->pluck('id');
    )
}

这将从以当前类别为父类别的类别中获取所有 id。然后使用 id 获取属于子类别的所有产品并计算它们。

上面的方法是一个访问器,所以你可以在玩具类别上调用它​​,比如$toyCategory->product_count

希望这能回答您的问题并让您朝着正确的方向前进。

旁注:这将为每个类别生成一个查询,这不是理想的方式,但它比为每个类别子生成一个查询要好。


推荐阅读