Doctrine 2.5 Comportamiento inesperado de búsqueda de asociación

Tengo 3 entidades asociadas de esta manera:

No te preocupes, he establecido asociaciones usando anotaciones, pero pensé que la siguiente combinación sería más clara / limpia para exponer mi problema

Post @ORM\ManyToOne(targetEntity="User", fetch="EAGER") - author User @ORM\OneToOne(targetEntity="Vip", mappedBy="user", fetch="EAGER") - vip Vip # Notice that the primary key of vip is a foreign key on User primary @ORM\id @ORM\OneToOne(targetEntity="User", inversedBy="peliqan", fetch="EAGER") @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false) - user 

Como puede ver, todo está listo para ser buscado con entusiasmo.

¿Qué necesito?

Me gustaría recuperar conjuntos de publicaciones junto con ambos Usuarios & VIP INFO SOLAMENTE, usando una sola consulta . (ver edición)

En este momento, por cada entrada posterior recibo una consulta adicional:

 SELECT t0.valid AS valid_1, ... FROM vip t0 INNER JOIN user t10 ON t0.user_id = t10.id WHERE t0.user_id = ? 

cuando:

  • Ejecuto esto

     $results = $qb ->select('ps') ->leftJoin('ps.author','u')->addSelect('u') ->add('where', $qb->expr()->in('ps.id', $ids)) ->getQuery()->getResult(); 
  • e incluso mientras trato de aplicar el modo FETCH_EAGER como este

     ->getQuery() ->setFetchMode('AppBundle\Entity\User', 'vip', ClassMetadata::FETCH_EAGER) ->getResult(); 

Nota:
Me las arreglé para deshacerme de la consulta adicional mediante la enforcingQuery::HYDRATE_ARRAY sobre la llamada getResult() .
Las consultas desaparecieron, lo que salvó un tercio del tiempo inicial.
La desventaja aquí es que al recuperar la asociación como matrices, no pude aprovechar Symfony\Component\Serializer\Annotation\Groups para filtrar las propiedades de las entidades y tuve que editar manualmente el conjunto de resultados para eliminar / transformar algunos valores.

EDITAR

La respuesta de Wilt está bien para la publicación original. No expuse mi problema de la manera correcta. Le dije que quería recuperar las informaciones de Vip porque pensé que era una buena manera de deshacerme de la consulta adicional de la que hablo arriba. En realidad , no necesito las informaciones de Vip, pero omitir ->leftJoin('u.vip','v')->addSelect('v') hace que la doctrine emita la consulta adicional que recostack las informaciones de Vip. ¿Hay alguna manera de evitar que la doctrine ejecute esta consulta?

Hay dos tipos de consultas de unión en Doctrine2:

1) Uniones regulares
2) Fetch une

Verifique la documentación capítulo 14.2.2. Se une para obtener más detalles.

Por lo tanto, si quiere buscar join vips, debe addSelect y leftJoin dentro de su consulta de la siguiente manera:

 $results = $qb ->select('ps') ->addSelect('u')->leftJoin('ps.author','u') ->addSelect('v')->leftJoin('u.vip','v') ->add('where', $qb->expr()->in('ps.id', $ids)) ->getQuery()->getResult(); 

ACTUALIZAR

Actualiza después de tu comentario:

Pensé que incluir vip en el conjunto de resultados sería la mejor manera de deshacerse de la consulta adicional

No puede deshacerse de la consulta adicional porque no puede cargar de forma diferida el lado inverso de una relación de uno a uno. Consulte también esta publicación para obtener más detalles:

Este es el comportamiento esperado. Los lados inversos de las asociaciones uno a uno no pueden ser flojos, técnicamente. No hay una clave externa en el lado inverso, por lo tanto, es imposible decidir si la proxy o no. Debemos consultar el objeto asociado o unirlo. Tenga en cuenta que esto solo afecta los lados inversos de las asociaciones de un solo valor, es decir, realmente solo el lado inverso de las asociaciones bidireccionales uno a uno.

  • Una solución podría ser invertir la relación para que el usuario se convierta en el lado propietario de la relación. En ese caso, al menos puede cargar vago Vip dentro de su entidad de User . El problema de la carga diferida se movería al lado Vip , lo que significa que ya no podría lazy-load su User en Vip más tiempo.

  • De lo contrario, podría hacer que su consulta devuelva un objeto parcial para evitar la carga de Vip , pero en general debe tener mucho cuidado con este enfoque.