php - 使用内部 Join 时如何优化 Doctrine 查询的数量?

标签 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

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

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

所以我开始使用查询生成器在 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();
}

我还是遇到了同样的问题。我已将方法中的选择参数更改为:

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();
}

Eureka ?好的,我只有一个查询,但我的方法不仅返回日志,还返回用户...所以我的 Twig 模板崩溃了,因为我的循环包含用户,而不仅仅是日志。当这是一个用户时,我的 View 崩溃了,因为我想写消息字段。 (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;
}

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

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

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

最佳答案

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

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

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

关于php - 使用内部 Join 时如何优化 Doctrine 查询的数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33476736/

相关文章:

jquery - jquery或symfony2上的图片存储库

symfony - 脚本缓存:clear returned with error code 1

php - 使用私有(private) API REST (Android + Symfony)

doctrine-orm - Doctrine 2 主/从连接

php - 如何使用 PHPUnit 在 Symfony2 中设置数据库密集型单元测试?

php - Symfony 网页包 : Could not find the entrypoints file from Webpack

php - 如何从 laravel Controller 打印变量?

Php 在 IIS7 上不报告任何错误

php - Favicon 存储和检索 |最佳实践

mysql - 从 2 个表中获取数据,在 Doctrine 上没有关系