如何在 Laravel 中为具有某种条件(例如是否有关系)的属性编写 orderBy 查询

how to write orderBy query for a attribute with some condition like has relation or not, in Laravel

我想编写一个查询以获取所有产品及其类型的列表。我喜欢按价格定单。 我的模型是这样的:

Product:
    id
    price
    ...

ProductType:
    id
    product_id
    price
    ...

产品有价格属性,部分产品有类型(一对多关系)。每种类型的产品都有自己的价格。当产品有类型时,它的价格为0。这意味着产品类型的价格对我们很重要。 现在,当我想将 orderBy 写入价格时,我不知道如何编写同时包含价格的查询,我的意思是当产品有类型时,我们查询第一种价格,当我们没有类型时,我们必须查询产品自己价格。 我在 Laravel.

中完成了所有这些
Products::with('types')->orderBy(???)->paginate(15);

我需要的目标是,如果我们想按最便宜的价格排序,首先显示价格最低或其中一种类型的价格最低的产品,依此类推。即,可能会出现一种情况,一种有类型的产品被放在2种没有类型的产品之间。

使用 sortBy... 会有帮助。

Products::with('productType')->get()->sortByDesc('productType.price');

或使用

[评论后编辑]

$sortDirection = 'desc';

  Products::with(['productType' => function ($query) use ($sortDirection) {
        $query->orderBy('price', $sortDirection);
    }])->get()->sortByDesc('price');

或型号

可以使用查询函数扩展关系:

 public function productType()
    {
        return $this->hasMany('ProductType')->orderBy('price');
    }

对我有用

[希望能奏效]

Product::with(['productType' => function ($query) use ($sortDirection) {
            $query->orderBy('price', $sortDirection);
        }])->get()->sortBy([
             fn ($a, $b) => $a['product_type.price'] <=> $b['price'],
         ]);


Products::with('productType')
    ->orderBy('price')
    ->orderBy(
          ProductType::select('price')
             ->whereColumn('products.id', '=' , 'product_types.product_id')
     );

您可以用作一个范围,您可以将订单方向传递给它,这样您就可以使用 desc 和 asc,例如

Product.php


public function scopeOrderedByProductTypesPrice($query, $order="asc"){

  $query
    ->orderBy('price')
    ->orderBy(
          ProductType::select('price')
             ->whereColumn('products.id', '=' , 'product_types.product_id')
     );
}

用例:


Products::with('productType')
        ->OrderedByProductTypesPrice('desc')
        ->get()

PS:如您所见,您还可以更新范围并接受列作为排序的参数

您可以使用leftJoin连接表并执行列求和,然后您可以对其进行排序。

Product::query()       
        ->leftJoin('product_types', 'products.id', '=', 'product_types.product_id')
        ->select([
            'products.id as product_id',
            'products.name as product_name',
            'products.price as product_price',

            'product_types.id as product_type_id',
            'product_types.name as product_type_name',
            'product_types.price as product_type_price',
            DB::raw('IFNULL((products.price), 0) + IFNULL((product_types.price), 0) as actual_product_prize'),            
        ])
        ->orderBy('actual_product_prize')
        ->get();

您不能使用关系进行排序,因为每个产品可能有不同的产品类型和不同的奖品,您不能使用关系进行排序。