在Eloquent中按关联字段排序

8

我希望使用Eloquent创建产品筛选器。

我从以下方式开始:

$query = Product::whereHas('variants')
        ->with('variants')
        ->with('reviews')

$query = $this->addOrderConstraints($request, $query);

$products = $query->paginate(20);

在哪里

private function addOrderConstraints($request, $query)
{
    $order = $request->input('sort');

    if ($order === 'new') {
        $query->orderBy('products.created_at', 'DESC');
    }

    if ($order === 'price') {
        $query->orderBy('variants.price', 'ASC');
    }

    return $query;
}

然而,这样做不起作用,因为Eloquent执行的查询如下所示(来自Laravel DebugBar的信息):
select count(*) as aggregate from `products` where exists 
(select * from `variants` where `products`.`id` = `variants`.`product_id`)

select * from `products` where exists 
(select * from `variants` where `products`.`id` = `variants`.`product_id`)

select * from `variants` where `variants`.`product_id` in ('29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48')

我尝试按价格排序时,出现了明显的错误。

等等,还有其他问题。

Unknown column 'variants.price' in 'order clause' (SQL: select * from 
`products` where exists (select * from `variants` where `products`.`id` =

能否使用Eloquent进行关联排序呢?

通过使用variants.product_id,按variants.price升序排列,取前20条数据(偏移量为0)。

所以,它是否可以执行关系排序呢?


你也可以尝试使用 $query->orderByRaw('variants.price asc'); - Casper Spruit
它确实不会改变查询,仍然是相同的。 - Thelambofgoat
2个回答

16

这将对子查询进行排序,而不是“第一个查询(即产品查询)”。

基本上,你的子查询将是:select * from variants where product_id in (....) order by price,这不是你想要的,对吧?

<?php 
// ...

$order = $request->sort;

$products = Product::whereHas('variants')->with(['reviews',  'variants' => function($query) use ($order) {
  if ($order == 'price') {
    $query->orderBy('price');
  }
}])->paginate(20);
如果您想对产品和/或变体进行排序,您需要使用连接(join)。
$query = Product::select([
          'products.*',
          'variants.price',
          'variants.product_id'
        ])->join('variants', 'products.id', '=', 'variants.product_id');

if ($order == 'new') {
    $query->orderBy('products.created_at', 'DESC');
} else if ($order == 'price') {
    $query->orderBy('variants.price');
}

return $query->paginate(20);

4
搜索“laravel关联关系orderBy”,没有人提到关系中的orderBy只对子查询进行排序,而不是第一个查询。谢谢! - Aslam H

5
如果您想对产品和变体进行排序,无需使用联接,因为您不会加载相关模型(例如 $product->variants),而只是加载变体表的所有字段。
要按相关子模型对模型进行排序,可以使用Eloquent-子查询排序
要按相关模型的顺序对整个模型进行排序,并且不是相关模型本身,可以像这样操作:
return Product::with('variants')->orderBy(
    Variants::select('price')
        // This can vary depending on the relationship
        ->whereColumn('variant_id', 'variants.id')
        ->orderBy('price')
        ->limit(1)
)->get();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接