doctrine2中的自定义DQL函数

时间:2014-07-17 09:40:03

标签: php mysql symfony doctrine-orm php-5.4

如何在partials中使用自定义DQL函数来水合查询结果。

寻找在createQuery或任何其他学说方式(nativeSql,QueryBuilder)中使用DQL函数的方法,它不需要使用partials但它应该根据表的关系来保持我的数组应该只选择选择性字段

以下查询工作正常:

$q = $em->createQuery("select "
                . "partial t.{id, description}, "
                . "partial ut.{id, firstName, lastName, email}, "
                . "DATE_FORMAT(ut.created, '%m-%d-Y') "
                . "from PMIUserBundle:Task t LEFT JOIN t.users ut");

DATE_FORMAT(ut.created,'%m-%d-Y')在偏出部分时工作正常。

DATE_FORMAT已在config.yml

中注册为自定义函数

config.yml:

dql:
            datetime_functions:
                DATE_FORMAT: PMI\UserBundle\DoctrineFunctions\DateFormat

以下查询会产生问题:

 $q = $em->createQuery("select "
                . "partial t.{id, description}, "
                . "partial ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}, "
                . "DATE_FORMAT(ut.created, '%m-%d-Y') "
                . "from PMIUserBundle:Task t LEFT JOIN t.users ut");

给出错误:

[Syntax Error] line 0, col 91: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_CURLY_BRACE, got '(' 

以下是我的DateFormat类:

class DateFormat extends \Doctrine\ORM\Query\AST\Functions\FunctionNode {



    protected $dateExpression;

    protected $formatChar;

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) {

         return 'DATE_FORMAT('.
                $sqlWalker->walkArithmeticExpression($this->dateExpression) .
                ','.
                $sqlWalker->walkStringPrimary($this->formatChar).
                ')';



    }

    public function parse(\Doctrine\ORM\Query\Parser $parser) {

        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->dateExpression = $parser->ArithmeticExpression();
        $parser->match(Lexer::T_COMMA);


        $this->formatChar = $parser->StringPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);


    }

}

编辑:

好的,所以Partial不允许我使用DQL函数。感谢FuzzyTree解决方案在我的实体类中使用ut->getFormattedCreatedDate()。但是我仍然很好奇如果我们将子表分组并使用mysql Aggregate函数计算一些数量。

如何使用createQuery,queryBuilder,nativeSQl或任何其他方式在doctrine2中实现以下条件:

  1. 仅选择选择性字段
  2. 使用聚合函数按子组实体分组
  3. 基于表关系的水合数组,聚合函数结果 应该是子数组。
  4. 每次如果我们使用DQL函数,我们是否必须像为DateFormat创建的那样创建类?如果我们使用嵌套的MySql函数,如

    ,该怎么办?
    GROUP_CONCAT(DISTINCT CONCAT(tags.id,',',tags.displayName)
    

    感谢您阅读我的问题。

3 个答案:

答案 0 :(得分:0)

  

如何在partials中使用自定义DQL函数来水合查询   结果

partial关键字告诉doctrine返回仅部分水合的实体,并允许您指定要水合的字段。

在检索部分实体时,您只能选择实体的字段(因为否则会在哪里教授'存储您选择的字段?),所以它不可能将DQL函数指定为部分对象的字段。

答案 1 :(得分:0)

这个怎么样?

    $qb = $this->_em->createQueryBuilder()
            ->select( 't.id, t.description, '
                    . 'ut.id, ut.firstName, '
                    . 'ut.lastName, ut.email, '
                    . 'DATE_FORMAT( ut.created, \'%m-%d-Y\' )' )
            ->from( 'PMIUserBundle:Task', 't' )
            ->leftjoin( 't.users', 'ut' );

    $result = $qb->getQuery()->getResult();

假设您在Repository类中使用它(这就是为什么调用$ this-> _em)。

我注意到有关自定义功能的其他两件事:

  1. 我个人将其定义为" string_functions:"而是在config.yml文件中
  2. 我至少知道一个实现此自定义功能的Bundle:https://github.com/beberlei/DoctrineExtensions
  3. 希望这有帮助,

答案 2 :(得分:0)

不支持

PARTIAL ut.{id, firstName, lastName, email, DATE_FORMAT(created, '%m-%d-Y')}

在选择像这样的部分实体中使用DQL函数不支持

它也没有多大意义。在这种情况下,您(可能)将字段created映射为datetime字段,因此您希望其中包含完整的DateTime值。但现在你突然只使用了日期部分。而且情况变得更糟:您以某种方式格式化了值,无法创建DateTime对象(它预期Y-m-d H:i:s,而date类型需要Y-m-d )。

对于任何部分选择:不能不应,更改字段的值。

替代

您可以只使用数组,而不是保湿到部分实体。使用$q->getArrayResult()$q->getScalarResult(),以更适合您的目的为准。

如果您愿意,可以将结果分组/嵌套在Repository方法中。例如:

public function getSomeData()
{
    $result = array();

    $dql = <<<EOQ
SELECT
t.id AS t_id,
t.description AS t_description,
u.id AS u_id,
u.firstName AS u_firstName,
u.lastName AS u_lastName,
u.email AS u_email,
DATE_FORMAT(u.created, '%m-%d-Y') AS u_created
FROM PMIUserBundle:Task t
LEFT JOIN t.users u
EOQ;

    $q = $this->getEntityManager()->createQuery($dql);

    foreach ($q->getScalarResult() as $row) {
        if (!isset($result[$row['t_id']])) {
            $result[$row['t_id']] = array(
                'id'          => $row['t_id'],
                'description' => $row['t_description'],
                'users'       => array()
            );

            $result[$row['t_id']]['users'][] = array(
                'u.id'        => $row['u_id'],
                'u.firstName' => $row['u_firstName'],
                'u.lastName'  => $row['u_lastName'],
                'u.email'     => $row['u_email'],
                'u.created'   => $row['u_created']
            );
        }
    }

    return $result;
}

嵌套DQL函数

嵌套DQL函数应该没问题(如果你正确编写它们)。并且DISTINCT支持开箱即用。