我如何将普通的SQL查询转换为准则ORM

时间:2019-02-19 08:00:26

标签: php symfony symfony-3.4

我刚刚开始研究Symfony 3.4和Doctrine ORM。我需要统计用户数。我测试了正常的查询,它工作正常。如何将普通查询转换为Doctrine ORM?任何帮助,将不胜感激。

"SELECT count(DATE_FORMAT(application.reviewed_at, '%Y-%m-%d')) AS count, user_id FROM application WHERE user_id = 6 AND DATE(reviewed_at) = CURDATE() GROUP BY DATE(reviewed_at)";

我尝试了以下代码。它不起作用。

$qb      = $em->createQueryBuilder();
$entries = $qb->select("count(DATE_FORMAT(application.reviewed_at, '%Y-%m-%d')) AS count", "user_id")
            ->where("user_id = 6", "DATE(reviewed_at) = CURDATE()")
            ->from('AppBundle\Entity\Application', 'u');
            ->groupBy("DATE(reviewed_at)");
            ->getQuery()
            ->getResult();

3 个答案:

答案 0 :(得分:2)

简而言之,Doctrine ORM并非旨在将SQL查询转换回DQL。 DQL是一种查询语言,可以转换为多个特定于供应商的SQL变体,因此这是从DQL到SQL的单向转换。

因此,如果您只有一个SQL查询,那么最好仅使用using Doctrine DBAL。当然,您可能必须处理结果集映射,但是可能无需将所有ORM内容拖到您的代码中。

您在这里所做的本质上是使用Doctrine的QueryBuilder API构建DQL查询。 FROM部分是绝对正确的,但是使用DATE_FORMATDATE函数的用户对我来说似乎是错误的。由于DQL转换为几种不同的SQL实现,具体取决于您使用的驱动程序,因此它需要一个兼容性层,因为DATE_FORMATDATECURDATE之类的功能并不是所有平台。

首先,看看documentation for user-defined functions。例如,MySQL中的DATEDIFF()函数就是一个很好的例子。如果事实证明还没有人实现对您正在使用的功能的支持,那么这是一个不错的起点,因为它基本上描述了如何实现对教义查询语言(DQL)的扩展。

第二,很有可能您正在使用的功能已经在某些第三方库中实现,例如OroCRM'sBenjamin Eberlei's Doctrine扩展集合。

此外,如果您要选择一个聚合或函数调用结果,最好给它加上别名。您可以在这里尝试使用$qb->expr()函数子集将DQL限制为更严格的语法。

答案 1 :(得分:0)

请务必记住,Doctrine DQL是不是 SQL方言。这是一种自定义语言,试图看起来与SQL相似,但是它使用Doctrine实体和关联而不是数据库表和列进行操作。当然,最后它会转换为SQL,但是在进行此转换之前,您需要保持DQL语法不变。

查询不起作用的原因之一是尝试在DQL查询中使用本机SQL(实际上是MySQL)功能。 DQL没有此类功能,此时您有2种方法:

  1. 以与Doctrine兼容的方式重写查询。它可能涉及数据库方案的更新。在您的特殊情况下,您可能希望将reviewet_at列从现在(我想是timestamp)转换为允许直接进行日期比较的date类型。它将使您摆脱自定义MySQL日期转换功能,并使查询与Doctrine兼容
  2. 您可以选择更艰难的路径,并直接在Doctrine中实现所有必需的自定义功能。这不是一件简单的事情,但是Doctrine足够灵活,可以为您提供这种能力。如果您有兴趣,可以在{Doctrine}文档中找到有关该主题的good article

答案 2 :(得分:0)

尝试尝试一下:

public function select()
{
    $queryBuilder = $this->createQueryBuilder('a');

    $queryBuilder
        ->addSelect(['a.user_id', $queryBuilder->expr()->count('a.reviewed_at')])
        ->where('a.user_id = :idUser')
        ->andWhere('a.reviewed_at = :date')
        ->setParameters([
            'idUser' => 6,
            'date' => new \DateTime(),
        ])
        ->groupBy('a.reviewed_at')
    ;

    return $queryBuilder
        ->getQuery()
        ->getResult()
    ;
}