【问题标题】:How to get products category wise in Laravel?如何在 Laravel 中明智地获取产品类别?
【发布时间】:2021-10-08 13:32:15
【问题描述】:

here 提出了类似的问题。

我正在研究 API。我的产品表包含一万多个不同类别的产品。我需要减少查询执行时间,因此为此,我必须修改一个 API,该 API 将仅获取每个类别的 20 个产品,并将整个 API 响应按类别分组。 API 响应如下所示。

{
"data": {
"products": {
  "Beauticians & Style": [
    {
      "Title": "Product A",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product B",
      "Price": "0.00",
      "DiscountPrice": 0
    }
  ],
  "Groceries": [
    {
      "Title": "Product G",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product R",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product O",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product C",
      "Price": "0.00",
      "DiscountPrice": 0
    }
  ],
  "Women's Fashion": [
    {
      "Title": "Product W",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product O",
      "Price": "0.00",
      "DiscountPrice": 0
    },
    {
      "Title": "Product M",
      "Price": "0.00",
      "DiscountPrice": 0
    }
  ]
}
}

控制器

$products = Category::with('products', function($q){
    $q->take(20);
})->get();

类别模型

class Category extends Model
{
    use HasFactory;

    public function products()
    {
        return $this->hasMany('App\Models\Product', 'CategoryID', 'CategoryID');
    }
}

我试过了,但没有得到确切的结果。

【问题讨论】:

    标签: php laravel-5 laravel-8


    【解决方案1】:

    当访问 Eloquent 关系作为属性时,相关模型是“延迟加载”这意味着在您第一次访问该属性之前不会实际加载关系数据。

    解决方法,你可以使用:

    $products = Category::with('products')
        ->get()
        ->map(function ($query) {
            $query->setRelation('products', $query->products->take(20));
            return $query;
        });
    

    参考:


    更新

    OP 评论:

    但在这种情况下,我们获取所有 10k 个产品,然后在集合上设置关系

    是的,这是性能问题,但是,您的问题是关于 eadger。 This is limitation

    Eloquent 作为工具,而不是解决方案。它只是 SQL 的一个包装器。如果您想将每个类别的产品数量限制为(n),则查询会变得复杂。

    要解决此问题,您需要使用window function

    SELECT * 
    FROM (
        SELECT
            *, 
            ROW_NUMBER() OVER (PARTITION BY `category_id`) AS row_num 
        FROM `products`
    ) AS temp_table 
    WHERE row_num <= 10 
    ORDER BY row_num
    

    或者,您可以使用this Laravel Eloquent extension 来允许使用窗口函数限制每个父级的急切加载结果的数量。

    类别模型

    use Staudenmeir\EloquentEagerLimit\HasEagerLimit;
    use App\Models\Product;
    
    class Category extends Model
    {
        use HasEagerLimit;
    
        public function products()
        {
            return $this->hasMany(Product::class);
        }
    }
    

    产品型号

    use Staudenmeir\EloquentEagerLimit\HasEagerLimit;
    
    class Product extends Model
    {
        use HasEagerLimit;
    }
    

    试试

    $products = Category::with(['products' => function ($query) {
        $query->latest()->limit(20);
    }])->get();
    

    这对你解释够了吗?

    【讨论】:

    • 但在这种情况下,我们正在获取所有 10k 产品,然后在集合上设置关系。
    【解决方案2】:

    如果每个产品只有一个类别,您的表格结构必须如下:

    products
        id
        ...
        category_id
    categories
        id
        ...
    

    并且您在 Category 中的产品关系必须如下:

    class Category extends Model
    {
        use HasFactory;
        public function products()
        {
            return $this->hasMany(App\Models\Product::class);
        }
    }
    

    并将您的控制器更改为:

    $products = Category::with('products', function($q){
                $q->take(20);
            })->get();
    

    【讨论】:

      猜你喜欢
      • 2021-11-24
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 2020-07-17
      • 2021-08-05
      • 1970-01-01
      相关资源
      最近更新 更多