【问题标题】:Perform order by relationship field in Eloquent在 Eloquent 中按关系字段执行排序
【发布时间】:2018-06-27 12:18:15
【问题描述】:

我想用 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` =

variants.product_id) order by variants.price asc limit 20 offset 0)

那么是否可以使用 Eloquent 进行关系排序?

【问题讨论】:

  • 你也可以试试$query->orderByRaw('variants.price asc');
  • 确实没有改变查询,还是一样

标签: laravel eloquent


【解决方案1】:

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

基本上,您的子查询将是: 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);

【讨论】:

  • 搜索laravel relationship order by,没有人提到orderBy内部关系只订购subQuery而不是first Query。谢谢!
【解决方案2】:

如果您想对产品和变体进行排序,则不需要连接,因为您不会加载相关模型(如 $product-&gt;variants),只需加载变体表的所有字段。

要按相关子模型对模型进行排序,我们可以使用Eloquent - Subquery Ordering

要按相关模型对整个模型进行排序,不是相关模型本身,我们可以这样做:

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();

【讨论】:

    猜你喜欢
    • 2016-06-21
    • 2015-06-21
    • 1970-01-01
    • 2013-11-03
    • 2021-01-25
    • 2014-06-25
    • 1970-01-01
    • 2019-04-12
    • 2021-07-14
    相关资源
    最近更新 更多