使用内部连接时如何优化 Doctrine 查询的数量?

Ale*_*ant 4 php symfony doctrine-orm

我必须简单实体:日志和用户。Log 与 Entity 有 ManyToOne 关系。

Log:
  type: entity
  repositoryClass: LogRepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    message:
      type: string      
  manyToOne:
    user:
      targetEntity: User
      joinColumns:
        user_id:
          referencedColumnName: id
Run Code Online (Sandbox Code Playgroud)

我的用例是显示日志列表和有关用户的一两个信息(例如他的姓名和他的邮件)

如果我使用该findall方法,Symfony 调试工具栏会显示 Doctrine 执行了大量查询。一个查询为我提供日志,并为每个用户执行一个查询!这当然不好,因为我可以看到一千个日志。我不想让我的数据库服务器过载。这个问题似乎很容易解决。但是我搜索了一段时间,结果似乎是“不良做法”。

所以我开始使用查询构建器在 LogRepository 类中编写一个新方法:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l')
            ->innerJoin(
                'ApplicationSonataUserBundle:User', 'u', 
                Expr\Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}
Run Code Online (Sandbox Code Playgroud)

我仍然有同样的问题。我已将方法上的选择参数更改为:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u', 
                        Expr\Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}
Run Code Online (Sandbox Code Playgroud)

尤里卡?好的,我只有一个查询,但我的方法不仅返回 Log,还返回 User...所以我的 Twig 模板崩溃了,因为我的循环包含 User,而不仅仅是 Log。当这是一个用户时,我的视图崩溃了,因为我想写消息字段。(Log.message 存在。但 User.message 不是一个有效的字段,当然)

它工作得很好,如果我用循环再改变一次我的方法来过滤我的结果:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u',
                        Expr\Join::WITH,'l.user = u.id')
        ;
        //THE STRANGE LOOP
        $results = array();
        foreach ($qb->getQuery()->getResult() as $result){
            if ($result instanceof Log){
                $results[] = $result;
            }
        };
        return $results;
}
Run Code Online (Sandbox Code Playgroud)

我只有一个查询,这就是我要搜索的内容。我的树枝模板没有崩溃,因为我的数组只包含日志。

那怎么回事?它有效,但我认为这不是好的/最佳实践。

有人可以向我解释一种更好的方法,一种使用内部联接查询的更好实践,以最小化执行的查询并获得仅包含 Log 实例的 ArrayCollection 结果?

Wil*_*ilt 5

应该没有必要使用循环。像这样尝试:

public function getLog(){
    $qb = $this->createQueryBuilder('l')
        ->select('l','u')
        ->innerJoin('l.user', 'u');
    $logs = $qb->getQuery()->getResult();
    return $logs;
}
Run Code Online (Sandbox Code Playgroud)

它应该只返回$logs填充(获取加入)关联用户。