【问题标题】:Doctrine DQL returning flat array from joinDoctrine DQL 从连接返回平面数组
【发布时间】:2016-12-14 15:37:54
【问题描述】:

我通过 DQL 中的常规 LEFT JOIN 选择 3 个实体。它们通过连接表相关联,连接表也为它们定义了实体以及带注释的关系。 查询执行没有问题,但我的结果作为平面数组返回。我希望一个包含三个实体的数组作为每个索引的数组元素:

SELECT e1, e2, e3 FROM AppBundle:EntityOne
JOIN AppBundle:JoinEntityOneWithTwo e1_2 WITH e1_2.entity1 = e1.id
JOIN AppBundle:EntityTwo e2 WITH e1_2.entity2 = e2.id
JOIN AppBundle:JoinEntityOneWithThree e1_3 WITH e1_3.entity1 = e1.id
JOIN AppBundle:EntityThree e3 WITH e3.id = e1_3.entity3
WHERE e1.some_field IN ('some','values','in','e1');

当我在查询中调用 getResult() 时,无论是作为对象还是数组进行水合,我都会得到一个平坦的结果集:

array(
 /AppBundle/Entity/EntityOne ( ... ),
 /AppBundle/Entity/EntityTwo ( ... ),
 /AppBundle/Entity/EntityThree  ( ... ),
 /AppBundle/Entity/EntityOne ( ... ),
 /AppBundle/Entity/EntityTwo ( ... ),
 /AppBundle/Entity/EntityThree  ( ... ),
 /AppBundle/Entity/EntityTwo ( ... ),
 /AppBundle/Entity/EntityThree  ( ... ),
 /AppBundle/Entity/EntityOne ( ... ),
)

我希望,或者喜欢有一个多维数组:

Array(
[0] => Array(
  [0] /AppBundle/Entity/EntityOne,
  [1] /AppBundle/Entity/EntityTwo,
  [2] /AppBundle/Entity/EntityThree
  ),
[1] => . . . 
)

结果不按行关联。它们也不是我可以用array_chunk()对它们进行分组的任何可预测的顺序

生成的 sql 运行良好。 DQL 返回准确的结果——它们只是没有按照我期望的方式制定。我正在关注有关急切加载连接的 Doctrine(难以捉摸的)文档:

http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html

这个问题和

很相似

Doctrine DQL returns multiple types of entities

但我的选择顺序不同,因为我的连接表是多对多的。 非常感谢!

有人问了这个问题的一个变种:

Getting Doctrine DQL results the SQL way

我很惊讶学说不支持通过连接表进行预加载。

【问题讨论】:

  • 要使用即时加载,您必须仅选择 e1 而不是 e1、e2 和 e3。
  • 是的,e1 在任何表上都没有外键引用。我可以通过选择 e1_2 来参与其中,但随后我失去了与 e3 的关系。

标签: php doctrine-orm symfony


【解决方案1】:

在您的查询中调用getScalarResult() 而不是getResult(),您会将所有连接表的所有字段合并到每条记录的一个数组中:

# Replace this call ...
$query->getQuery()->getResult();
# ... by that call ...
$query->getQuery()->getScalarResult();

【讨论】:

    【解决方案2】:

    这是我能想到的最好的:

    //in my entity repository:
    public function getFoo($hydrate = true) {
      $sql = "SELECT e1, e2, e3 FROM entity_one
              JOIN entity_one_entity_two e1_2 ON e1_2.entity_one_id = e1.id
              JOIN entity_two e2 ON e1_2.entity_two_id = e2.id
              JOIN entity_one_entity_three e1_3 ON e1_3.entity_one_id = e1.id
              JOIN entity_three e3 ON e3.id = e1_3.entity_three.id
              WHERE e1.some_field IN ('some','values','in','e1')";
      $stmt = $con->prepare($sql);
            $stmt->execute();
      return ($hydrate)
        ? $this->hydrateResponses($stmt->fetchAll(PDO::FETCH_ASSOC))
           : $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    public function hyrdateResponses($responses) {
      //call find by ids on repositories from array.
    }
    

    这很有效,因为当您只尝试从一个查询中获取结果时,您执行的查询数量是 3 倍!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      相关资源
      最近更新 更多