php - generate - Doctrine QueryBuilder indexBy en la clase unida-p ya está definido Error
query builder symfony (1)
Al usar symfony2 / doctrine2, me cuesta definir un índice para mi consulta.
Mi código :
$queryBuilder = $this->_em
->createQueryBuilder()
->select(''u, uis, cost, p, stock'')
->from(''AppBundle:FoodAnalytics/UserIngredient'', ''u'', ''p.id'')
->leftJoin(''u.product'', ''p'')
->leftJoin(''u.numberObjects'', ''stock'')
->leftJoin(''u.userIngredientSuppliers'', ''uis'')
->leftJoin(''uis.numberObjects'', ''cost'')
->where(''u.user = ?1'')
->setParameter(1, $portfolioUser)
;
Obtuve el siguiente error :
[Semantical Error] line 0, col 110 near ''p LEFT JOIN u.numberObjects'': Error: ''p'' is already defined.
500 Internal Server Error - QueryException
1 linked Exception: QueryException »
[1/2] QueryException: SELECT u, uis, cost, p, stock FROM AppBundle:FoodAnalytics/UserIngredient u INDEX BY p.id LEFT JOIN u.product p LEFT JOIN u.numberObjects stock LEFT JOIN u.userIngredientSuppliers uis LEFT JOIN uis.numberObjects cost WHERE u.user = ?1 +
Usando u.product
me sale el siguiente error:
[Semantical Error] line 0, col 87 near ''product LEFT'': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
500 Internal Server Error - QueryException
1 linked Exception: QueryException »
Usando el product
, me sale el siguiente error:
[Semantical Error] line 0, col 85 near ''product LEFT'': Error: ''product'' does not point to a Class.
500 Internal Server Error - QueryException
1 linked Exception: QueryException »
Funciona bien si uso u.id
¿Puedo usar index por un campo de la misma tabla?
¿Qué puedo hacer para que funcione?
Thansk mucho!
EDITAR:
Como solución temporal, estoy usando:
$result = $queryBuilder->getQuery()->getResult();
$result = array_combine(array_map(function(UserIngredient $userIngredient){
return $userIngredient->getProduct()->getId();
}, $result), $result);
return $result;
El indexBy
atributos solo se aplica a la entidad que está seleccionando actualmente, como ha adivinado (y AFAIK); entonces en tu caso solo puedes indexar por u.id
.
Esto tiene sentido para mí, ya que la indexación de otra entidad realmente arruina los resultados devueltos. La única situación en la que obtendrás el resultado correcto es cuando:
- todas las uniones de la entidad principal y el índice "objetivo" para la entidad son uno a uno;
- todas las uniones son INNER JOIN;
- la columna indexBy del conjunto de resultados es única.
En cualquier otro caso pierdes alguna referencia de instancia durante la hidratación.
En su ejemplo, usted está usando LEFT JOIN: ¿qué pasará con todas las entidades sin producto? Todos descartados, por lo que LEFT JOIN tendría un trabajador como INNER JOIN. Además, su solución alternativa sugiere que desea combinar entidades con el mismo índice, pero no es así como funciona Doctrine: en Doctrine, una columna indexBy DEBE ser única. Ver los documentos oficiales para más información.
Tenga en cuenta que puede indexar By p.id
en su cláusula JOIN, pero esto tiene un significado diferente. Significa que al hidratar las instancias de UserIngredients, la recopilación del producto debe indexarse mediante id.
Entonces, mi sugerencia es seguir una de estas dos soluciones:
- renunciar a Doctrine indexBy, y usar su entorno de trabajo;
- Si tiene la asociación inversa
Product -> UserIngredients
, useProduct
como la entidad principal de la consulta (la cláusula from, y primero para que aparezca en select), y luego indexe porp.id
Cuál usar depende de la lógica de su negocio, pero generalmente prefiero la segunda solución, ya que la primera genera matriz de múltiples niveles, que están mejor representadas por las relaciones entre entidades.
¡Espero que esto ayude! :)