Intereting Posts
Как разместить div в пользовательском месте на странице Использование этого в массиве вызывает неожиданный T_Variable MySQL наибольшее значение в строке? Пользовательский селектор выпадающего меню, отображающий или скрывающий другие настраиваемые поля Checkout Magento: исключение «Zend_Mail_Transport_Exception» с сообщением «Невозможно отправить почту вызов функции javascript из php как передать переменную POST по ссылкам на собственные страницы? Как загрузить файл с сервера, используя PHP Code Как обновить значения в моей БД новыми значениями из тегов <select> и <input>? Передача ключей массива и значений в строку запроса Mysql Эффективное сохранение загруженных пользователем изображений в файловой системе Процент символа в URI CodeIgniter Другая проблема с правами доступа к файлам Как добавить пользовательские правила валидации при использовании проверки формы запроса в Laravel 5 Проверка формы отправки – PHP

CakePHP 3 содержат поля выбора

У меня есть следующие таблицы БД: элементы, пользователи, группы, itemImages. Между (элементами, группами) и (пользователями, группами) существует много разных отношений, а между ними (между пунктами, itemImages). Все соответствующие внешние ключи были настроены в CakePHP как ассоциации.

Как я могу построить запрос с функцией contains (), который выбирает все элементы и их основное изображение, которые находятся в группе, которая была назначена в качестве основной группы для пользователя с определенным идентификатором?

Чтобы сделать его более понятным, вот как выглядит простой SQL-запрос:

SELECT items.id AS itemId, items.name, itemImages.url AS itemUrl FROM items INNER JOIN groups_items ON groups_items.item_id = items.id INNER JOIN groups ON groups_images.group_id = groups.id INNER JOIN groups_users ON groups_users.group_id = groups.id INNER JOIN users ON groups_users.user_id = users.id INNER JOIN itemImages ON itemImages.item_id = items.id WHERE groups_users.isMainGroup = 1 AND users.id = :userId AND itemImages.isMainImage = 1 

Код CakePHP, который у меня есть сейчас:

 $items = $this->Items->find() ->hydrate(false) ->contain([ 'Groups.Users' => function($q) use ($userId){ return $q->where(['isMainGroup' => 1, 'Users.id' => $userId]); }, 'ItemImages' => function($q){ return $q->where(['isMainImage' => 1]); }, ]); //->select(['itemId' => 'Items.id', 'Items.name', 'itemUrl' => 'itemImages.url']); 

метод matching () может помочь с этим

 $items = $this->Items->find() ->hydrate(false) ->select(['Items.id', 'Items.name', 'itemImages.url']) ->distinct(['Items.id']) ->matching('Groups.Users', function ($q) use ($userId) { return $q->where(['Groups.isMainGroup' => 1, 'Users.id' => $userId]); }) ->matching('ItemImages', function ($q) { return $q->where(['ItemImages.isMainImage' => 1]); }) ->contain([ 'ItemImages' => function ($q) { return $q->autoFields(false) ->select(['id','url']) ->where(['ItemImages.isMainImage' => 1]); } ]); 

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

Примечание по теме distict () :

Поскольку эта функция создаст INNER JOIN, вы можете подумать о том, чтобы вызывать отдельный запрос на поиск, поскольку вы можете получать повторяющиеся строки, если ваши условия не фильтруют их уже

http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#filtering-by-associated-data