Doctrine orm 条令:QueryBuilder与createQuery?

Doctrine orm 条令:QueryBuilder与createQuery?,doctrine-orm,Doctrine Orm,在Doctrine中,您可以通过两种方式创建DQL: EntityManager::createQuery: $query = $em->createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1'); $qb->add('select', 'u') ->add('from', 'User u') ->add('where', 'u.id = ?1') ->add('orde

在Doctrine中,您可以通过两种方式创建DQL:

EntityManager::createQuery

$query = $em->createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1');
$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('where', 'u.id = ?1')
   ->add('orderBy', 'u.name ASC');
QueryBuilder

$query = $em->createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1');
$qb->add('select', 'u')
   ->add('from', 'User u')
   ->add('where', 'u.id = ?1')
   ->add('orderBy', 'u.name ASC');
我想知道区别是什么,我应该用哪一种

  • DQL更易于阅读,因为它与SQL非常相似。如果不需要根据一组参数更改查询,这可能是最佳选择

  • QueryBuilder是一个用于构造查询的api,因此,如果您需要像迭代一组参数或过滤器一样动态地构建查询,则更容易实现。您不需要执行任何字符串操作来构建查询,比如join、split或其他什么


  • 比如说,查询生成器只是创建查询的接口。。。它的使用应该更舒适,它不仅有add()方法,还有where()、andWhere()、from()等方法。但最后,它只是像createQuery()方法中使用的那样组合查询

    查询生成器的更高级使用示例:

    $em->createQueryBuilder()
                ->from('Project\Entities\Item', 'i')
                ->select("i, e")
                ->join("i.entity", 'e')
                ->where("i.lang = :lang AND e.album = :album")
                ->setParameter('lang', $lang)
                ->setParameter('album', $album);
    

    它们有不同的目的:

    • 当您了解完整查询时,DQL更易于使用
    • 当您必须基于某些条件、循环等构建查询时,查询生成器更为智能

    主要区别在于调用方法的开销。为了简单起见,您的第一个代码示例(createQuery)进行了一次方法调用,而queryBuilder进行了4次。在一切结束时,它们归结为一个必须执行的字符串,第一个示例是给它字符串,另一个示例是用多个链式方法调用构建它


    如果你正在寻找一个理由来使用一个而不是另一个,这是一个风格的问题,什么看起来更具可读性。对我来说,我大部分时间都喜欢QueryBuilder,它为查询提供了定义良好的部分。此外,在过去,当您需要条件逻辑时,可以更容易地添加它。

    使用查询生成器时,单元测试可能更容易。假设您有一个基于复杂条件列表查询某些数据的存储库。您希望确保,如果将特定条件传递到存储库中,则会将其他一些条件添加到查询中。对于DQL,您有两个选项:

    1) 使用夹具并测试与DB的真实交互。我觉得这有点麻烦和不自然

    2) 检查生成的DQL代码。这会让你的测试太脆弱


    使用QueryBuilder,您可以用mock替换它,并验证是否调用了带有所需参数的“andWhere”方法。当然,如果您的查询很简单并且不依赖于任何参数,那么这些注意事项就不适用了。

    但是在第一种情况下,解析DQL字符串不是有开销吗?或者生成器也会生成相同的DQL字符串?是的,QueryBuilder会为您创建DQL字符串。在这之后,DQL无论如何都会被解析。你可以添加->setParameters(数组('x'=>'y','z'=>'w',…)一个小小的观察-我想说,几乎任何一个人花费在任何数量的PHP函数调用上的时间,与SQLing相关,总是比与数据库对话、等待和从数据库中提取实际结果所花费的时间要少(更不用说在发生ORMs的情况下对其进行水合)。