Laravel Eloquent сортировать по столбцу таблицы отношений

Я попытался сортировать продукты из таблицы shop_products помощью pinned столбца из таблицы shop_products_options :

 $products = Shop\Product::with(['options' => function ($query) { $query->orderBy('pinned', 'desc'); }])->paginate(5); 

Я установил отношение в Shop \ Product model:

 public function options() { return $this->hasOne('Shop\Options'); } 

Но продукты не сортируются. Я получаю запрос, который работает только с таблицей shop_products_options .

 SELECT * FROM `shop_products_options` WHERE `shop_products_options`.`product_id` in ('8', '9', '10', '11', '12') ORDER BY `pinned` DESC 

Как это исправить?

Желаемая загрузка использует отдельные запросы, поэтому вам необходимо присоединиться к этому:

 $products = Shop\Product::join('shop_products_options as po', 'po.product_id', '=', 'products.id') ->orderBy('po.pinned', 'desc') ->select('products.*') // just to avoid fetching anything from joined table ->with('options') // if you need options data anyway ->paginate(5); 

Предложение SELECT существует, чтобы не присоединить объединенные столбцы к вашей модели Product .


edit: согласно комментарию @alexw – вы все равно можете включать столбцы из объединенных таблиц, если они вам понадобятся. Вы можете добавить их, чтобы select или вызвать addSelect/selectRaw и т. Д.

Вы не можете сортировать по соответствующему столбцу таблицы без привязки вручную к связанной таблице. Ответ Джарека правильный, но это может быть очень неудобно:

1. Первая проблема заключается в том, что вам нужно беспокоиться о выборе.

 ->select('products.*') 

Причина: без select () id из shop_products_options можно выбрать и увлажнить модель продукта.

Вторая проблема заключается в том, что вам нужно беспокоиться о groupBy.

 ->groupBy('products .id'); 

Причина: если отношение HasOne и для продукта более одного shop_products_options, запрос возвращает больше строк для продуктов.

3. Третья проблема заключается в том, что вам нужно изменить все остальные, где:

 ->where('date', $date) 

в

 ->where('products .date', $date) 

Причина: продукты и shop_products_options могут иметь атрибут «дата», и в этом случае без выбора атрибута с таблицей «неоднозначный столбец» будет выведена ошибка.

4. Четвертая проблема заключается в том, что вы используете имена таблиц (а не модели), и это также плохо и неудобно.

 ->where('products.date', $date) 

5. Пятая проблема заключается в том, что вам нужно беспокоиться о мягких ударах для объединенных таблиц. Если shop_products_options использует свойство SoftDeletes, вы должны добавить:

 ->where('shop_products_options .deleted_at', '=', null) 

Все вышеперечисленные проблемы очень расстраивают, и объединение таблиц с красноречием может привести к вашему коду многих проблем. Я создал пакет, который заботится обо всех вышеперечисленных проблемах, и вы можете сортировать по атрибуту отношения с элегантным способом, для вашего случая это будет:

 $products = Shop\Product::orderByJoin('options.pinned', 'desc')->paginate(5); 

Для получения дополнительной информации см. https://github.com/fico7489/laravel-eloquent-join