laravel, несколько вопросов

VHS
На сайте с 28.09.2007
Offline
142
VHS
263

Начинаю окунаться в лару, никак не могу понять, как мне сделать следующее:

Три таблицы:

catalogs

catalog_product

product

Продукт может принадлежать нескольким группам. Таблица catalog_product связующая.

Связь между catalogs и  catalog_product не по первичному ключу, а по уникальному UID.

Имена полей в  catalog_product catalog и product

Первичный ключ продукта - UID

1) Как правильно описать взаимосвязь через таблицу, для получения всех продуктов каталога?

2) Как получить все продукты текущего и дочерних каталогов (используется nested sets) ? Сейчас получаю не совсем красиво, через подготовку массива и whereIn

VHS
На сайте с 28.09.2007
Offline
142
VHS
#1
Отвечу сам себе. Все отлично работает через 

hasManyThrough

с одним нюансом - в отладчике нет информации о запросе, которым это было сделано. Что тут за магия - я не могу понять.

A
На сайте с 17.01.2019
Offline
19
#2
Лог запросов из отладчика в студию. Насколько я помню, там надо указывать опцию для явного джоина, чтобы был сложный запрос с джоином, либо илокент делает запросы с подзапросами или в несколько отдельных запросов получает данные и сводит их вместе.
VHS
На сайте с 28.09.2007
Offline
142
VHS
#3

Кирилл, спасибо за отклик. Удивительнейшим образом сегодня все заработало. 

Все оказалось просто. Запрос был частью системы динамического роутинга каталога, очень похоже на вот этот пример (https://gtxtymt.xyz/blog/laravel-pages-from-database). Т.к. эту часть я делал достаточно давно, а потом на несколько месяцев забросил проект, то и воспоминаний о кешировании у меня не осталось =) Убрал ->with('products'), почистил кэш, подзапросы пошли. 

Работа с динамическими страницами в Laravel
Работа с динамическими страницами в Laravel
  • 2019.03.16
  • gtxtymt.xyz
Очень часто, я бы даже сказал практически в каждом проекте возникает необходимость создать "динамические страницы" - страницы с одной сущностью, разным содержимым и без какого-либо паттерна для конфигурации конечного адреса, по которому сущность будет отображаться. Конечный адрес может иметь неограниченное количество уровней - от банального до...
Н
На сайте с 27.02.2013
Offline
78
#4
Ссылки не индексируются.
VHS
На сайте с 28.09.2007
Offline
142
VHS
#5

Посмотри на мою дату регистрации и подумай, нужна ли мне эта информация или нет?)


Теперь осталось разобраться со второй частью вопроса - как красиво отобрать все продукты в текущей и дочерних каталогах ) 

Пока сделано по старинке : 

$groupsArray[] = $group->UID;
$descendants = $group->descendants()->defaultOrder()->get();
foreach ($descendants as $model) {
$groupsArray[] = $model->UID;
}


$products = CatalogProduct::whereIn('catalog_products.catalog_UID', $groupsArray)
->leftJoin('products', 'products.UID', '=', 'catalog_products.product_UID')
->where('products.price', '>', 0)
->orderBy($sortField, $sortWay)
->get();

Оно конечно работает, но просто интересно, есть ли красивые решения. Ну и еще момент, при такой выборке возможны дубли продуктов, чего конечно бы не хотелось, нужно только первый.

A
На сайте с 17.01.2019
Offline
19
#6

Дублей можно избежать с помощью `distinct()`. Надо играться и смотреть итоговый запрос.

Обычно я в таких ситуациях сначала генерирую нужный SQL, а потом перетаскиваю его в ActiveRecord, если это необходимо. Так удобнее, чем возиться с магией эктиврекорда. 

И в `whereIn` ты можешь подзапрос положить по типу `WHERE IN (SELECT id FROM ...)`. Тогда не придётся логику какую-то на php описывать. На малой нагрузке так будет ок, а на большой стоит смотреть на перфоманс, чтобы понимать какой из вариантов будет лучше отрабатывать.

PS. Отвратительный редактор сообщений, ещё и без поддержки маркдауна. Я сломал всё вокруг, но не смог оформить инлайн-код, поэтому пусть будет так, как я написал.

VHS
На сайте с 28.09.2007
Offline
142
VHS
#7

Благодарю за советы!

distinct использовать не удалось, но получился не сильно страшный по производительности, и главное рабочий запрос

$products = CatalogProduct::select('*')->from(
DB::table('catalog_products')
->selectRaw('MAX(catalog_UID) AS catalog_UID, product_UID')
->whereIn('catalog_UID', $groupsArray)
->groupBy('product_UID')
)
->leftJoin('products', function ($join) {
$join->on('products.UID', '=', 'product_UID')
->where('products.price', '>', 0);
})

->orderBy($sortField, $sortWay)
->paginate(12);

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий