Perform order by relationship field in Eloquent

 ̄綄美尐妖づ 提交于 2020-08-23 03:35:33

问题


I want to create product filter with Eloquent.

I start like this

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

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

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

Where

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;
}

However, that doesn't work, cause Eloquent is performing this query like this (information from 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')

And so on

So when I try to use sorting by price it just obvious error

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)

So is it possible to perform relationship ordering with Eloquent or not?


回答1:


This will sort the subquery. Not the "first query (the product query)".

Basically, your subquery will be: select * from variants where product_id in (....) order by price, and that is not what you want, right?

<?php 
// ...

$order = $request->sort;

$products = Product::whereHas('variants')->with(['reviews',  'variants' => function($query) use ($order) {
  if ($order == 'price') {
    $query->orderBy('price');
  }
}])->paginate(20);

If you want to sort product +/or variant you need to use 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');
}

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

return $query->paginate(20);


来源:https://stackoverflow.com/questions/48321076/perform-order-by-relationship-field-in-eloquent

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!