Я попытался сортировать продукты из таблицы 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