Doctrine嵌套多个连接

时间:2011-03-26 21:17:22

标签: join symfony1 doctrine

我正在尝试使用Doctrine优化symfony应用程序。我偶然发现了以下问题:

在视图中我使用了$ project-> getProgress();但是通过这样做,查询的数量会随着项目的增加而增加。所以我尝试使用左连接将进度放入项目查询(覆盖findAll方法),但这没有用。查询数量实际上增加了。

public function findAll($hydrationMode = null)
{
    $q = $this->createQuery('p')
                    ->leftJoin('p.progress pr')
                    ->leftJoin('pr.sfGuardUser u')
                    ->leftJoin('p.raws r')
                    ->leftJoin('p.series');
    return $q->execute(array(), $hydrationMode);
}

这是我尝试使用尽可能少的查询创建的结果:

array() {
  [0]=>
  array() {
    ["id"]=> string(1) "1"
    ...
    ["progress"]=>
    array() {
        array() {
            array() { progress1 }
            array() { progress2 }
            array() { progress3 }
            ....
        }
    }
  }

我查看了symfony和Doctrine的文档,但找不到我的答案。我也在谷歌搜索了很长一段时间。 (我一直在寻找解决方案已经有几个月了)我希望我已经足够好地描述了我的问题。

的schema.yml:

projects:
  actAs:
    Timestampable: ~
  columns:
    user_id: integer(4)
    series_id: bigint
    pages: int
    chapter: string
    translators_id: bigint
    proofreaders_id: bigint
    cleaners_id: bigint
    typesetters_id: bigint
    raws_id: bigint
    hide_project: bool
    complete: bool
  relations:
    sfGuardUser:
      local: user_id
      foreign: id
      onDelete: CASCADE
    series:
      local: series_id
      foreign: id
      type: one
      foreignType: many
      onDelete: CASCADE
    progress:
      local: id
      foreign: projects_id
      onDelete: CASCADE
      type: one
      foreignType: many

projectsProgress:
  actAs: [Timestampable]
  columns:
    projects_id: bigint
    user_id: integer(4)
    job:
      type: enum
      notnull: true
      values: [tl,pr,cl,ts]
    beginpage: int
    endpage: int
    complete: bool
    file: string
    url: clob
  relations:
    sfGuardUser:
      local: user_id
      foreign: id
      onDelete: CASCADE
    projects:
      local: projects_id
      foreign: id
      onDelete: CASCADE
      foreignAlias: progress

2 个答案:

答案 0 :(得分:0)

您需要修改提取Project对象以包含联接的查询。通常,获取Project个对象的查询应放在ProjectTable

如果您要修改Project的所有查询或查询子集,请查看Doctrine Query Execution Listeners

答案 1 :(得分:0)

使用水合物模式的问题是您可以获取不使用的数据。我真的不知道doctrine如何获取所有数据,但是假设每个项目都会带来所有必需的数据,至少会增加一个查询......

对于复杂查询(和优化),我更喜欢进行手动查询,并设法将所有需要的数据放在一个查询中,例如:

$query = "SELECT ... FROM projects p LEFT JOIN progress pr (LEFT JOIN sfGuardUser u (LEFT JOIN...) ON pr.user_id = u.id ) ON p.id = pr.projects_id"

$rs = Doctrine_Manager::getInstance()->getCurrentConnection()->fetchAssoc($query);

$ rs 包含所选数据的数组。拥有所有数据,您可以根据需要创建数组,但请记住,这样您可以执行一个查询(减少数据库负载),但添加一些时间机器解析数组。