CakePHP 3 contiene campos selectos

Tengo las siguientes tablas de base de datos: elementos, usuarios, grupos, itemImages. Hay muchas o muchas relaciones entre (elementos, grupos) y (usuarios, grupos), y uno a muchos entre (elementos, itemImages). Todas las claves externas apropiadas se han configurado en CakePHP como asociaciones.

¿Cómo puedo crear una consulta con contain () que selecciona todos los elementos y su imagen principal, que están en un grupo que se ha asignado como grupo principal a un usuario con un ID en particular?

Para hacerlo más claro, aquí es cómo se vería una consulta SQL simple:

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 

El código de CakePHP que tengo por ahora:

 $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']); 

El método matching () puede ayudar con esto

 $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]); } ]); 

Creo que, en este caso, se puede omitir la última instrucción contenida porque el resultado deseado ya está en la propiedad _matchingData .

Nota sobre la estructura distict () :

Como esta función creará una UNIÓN INTERNA, es posible que desee considerar realizar una llamada distinta en la consulta de búsqueda, ya que puede obtener filas duplicadas si sus condiciones ya no las filtran.

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