使用symfony2/doctrine2,我很难为查询定义索引。
我的代码:
$queryBuilder = $this->_em
->createQueryBuilder()
->select('u, uis, cost, p, stock')
->from('AppBundle:FoodAnalyticsUserIngredient', '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)
;
我得到以下错误:
[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:FoodAnalyticsUserIngredient 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 +
使用u.product
,我得到以下错误:
[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 »
仅使用product
,我得到以下错误:
[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 »
如果我使用u.id
,效果会很好我只能使用同一表中某个字段的索引吗?
我该怎么做才能让它正常工作?
Thansk很多!
编辑:
作为临时修复,我正在使用:
$result = $queryBuilder->getQuery()->getResult();
$result = array_combine(array_map(function(UserIngredient $userIngredient){
return $userIngredient->getProduct()->getId();
}, $result), $result);
return $result;
属性indexBy
仅适用于您当前选择的实体,正如您所猜测的(以及AFAIK);所以在您的情况下,您只能通过u.id
进行索引。
这对我来说是有意义的,因为从其他实体进行索引确实会打乱返回的结果。唯一能得到正确结果的情况是:
- 来自主实体和"目标"indexBy实体的所有联接都是一对一的
- 所有联接都是INNER join
- 结果集的indexBy列是唯一的
在其他任何情况下,你都会在水合过程中失去一些实例参考。
在您的示例中,您正在使用LEFT JOIN:没有产品的所有实体会发生什么?全部丢弃,所以LEFT JOIN将具有类似INNER JOIN的worker。此外,您的变通方法建议您希望将具有相同索引的实体组合在一起,但这不是Doctrine的工作方式:在Doctrine中,indexBy列必须是唯一的。有关更多信息,请参阅官方文档。
请注意,您可以在JOIN子句中indexByp.id
,但这有不同的含义。这意味着,当对UserIngredients实例进行水合时,产品集合应该通过id进行索引。
因此,我的建议是遵循以下两种解决方案之一:
- 放弃Doctrine indexBy,使用您的工作环境
- 如果有反向关联
Product -> UserIngredients
,请使用Product
作为查询的主要实体(from子句,首先出现在select中),然后按p.id
进行索引
使用哪一个取决于您的业务逻辑,但我通常更喜欢第二个解决方案,因为第一个解决方案生成多级数组,它们可以更好地用实体关系表示。
希望得到帮助!:)