У меня есть следующие таблицы БД: элементы, пользователи, группы, 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