Doctrine QueryBuilder indexBy on join class -p已经定义了Error

Séb*_*ien 13 php mysql query-builder symfony doctrine-orm

使用symfony2/doctrine2,我很难为我的查询定义索引.

我的代码:

    $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)
        ;
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

[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   +
Run Code Online (Sandbox Code Playgroud)

使用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 »
Run Code Online (Sandbox Code Playgroud)

使用just 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 »
Run Code Online (Sandbox Code Playgroud)

如果我使用它可以正常工作我u.id 可以只使用同一个表中的字段索引吗?

我能做些什么才能让它发挥作用?

Thansk很多!

编辑:

作为我正在使用的临时修复:

    $result = $queryBuilder->getQuery()->getResult();
    $result = array_combine(array_map(function(UserIngredient $userIngredient){
                return $userIngredient->getProduct()->getId();
            }, $result), $result);
    return $result;
Run Code Online (Sandbox Code Playgroud)

gio*_*mhz 5

正如您所猜测的(并且据我所知),该属性indexBy仅适用于您当前选择的实体;所以在你的情况下你只能索引u.id

这对我来说很有意义,因为从其他实体建立索引确实会弄乱返回的结果。您获得正确结果的唯一情况是:

  • 来自主实体和“目标”indexBy 实体的所有连接都是一对一的;
  • 所有连接都是INNER JOIN;
  • 结果集的indexBy列是唯一的。

在所有其他情况下,您都会在水合过程中丢失一些实例引用。

在您的示例中,您使用的是 LEFT JOIN:没有产品的所有实体会发生什么?全部被丢弃,因此 LEFT JOIN 会有像 INNER JOIN 一样的工作人员。另外,您的解决方法建议您想要组合具有相同索引的实体,但这不是 Doctrine 的工作方式:在 Doctrine 中,indexBy 列必须是唯一的。查看官方文档以获取更多信息。

请注意,您可以indexByp.id在 JOIN 子句中使用 indexBy,但这具有不同的含义。这意味着在对 UserIngredients 实例进行水合时,产品集合应按 id 进行索引。

因此,我的建议是遵循这两个解决方案之一:

  • 放弃 Doctrine indexBy,并使用你的解决方法;
  • 如果有逆关联Product -> UserIngredients,请使用Product作为查询的主要实体(from 子句,并且首先出现在 select 中),然后索引 by p.id

使用哪一个取决于您的业务逻辑,但我通常更喜欢第二种解决方案,因为第一个生成多级数组,可以更好地用实体关系表示。

希望这有帮助!:)