简体   繁体   中英

Symfony2: Doctrine MySql Math Functions

I try to get count of persons by age bracket.

AGEBRACKET | NBR
    10     |  3
    20     |  14
    30     |  123
    40     |  4
    50     |  55
...

This is my code:

$qb = $em->createQueryBuilder();
    $qb->select('FLOOR((YEAR(CURDATE())-YEAR(p.date_birth)) / 10) * 10 AS age, COUNT(p.id)');
    $qb->from('MyBundle:Person', 'p');
    $qb->groupBy('age');
    $countByAge = $qb->getQuery()->execute();

I get this error:

[Syntax Error] line 0, col 7: Error: Expected known function, got 'FLOOR'

I look a little bit for a solution, and this is what have I found:

<?php
namespace MyProject\Query\AST;

use \Doctrine\ORM\Query\AST\Functions\FunctionNode;
use \Doctrine\ORM\Query\Lexer;

class MysqlFloor extends FunctionNode
{
    public $simpleArithmeticExpression;

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FLOOR(' . $sqlWalker->walkSimpleArithmeticExpression(
            $this->simpleArithmeticExpression
        ) . ')';
    }

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $lexer = $parser->getLexer();

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

        $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

<?php
\Doctrine\ORM\Query\Parser::registerNumericFunction('FLOOR', 'MyProject\Query\MysqlFloor');
$dql = "SELECT FLOOR(person.salary * 1.75) FROM CompanyPerson person";

And I get another error:

Attempted to call method "registerNumericFunction" on class "Doctrine\ORM\Query\Parser".

Have you any idea how I can do to have the desired result.

Thanks

There's an updated version in the Doctrine docs that should help you: http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#adding-your-own-functions-to-the-dql-language

If you want to add it to your Symfony config so it can be used everywhere in your project, see http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html for how you can do that.

The solution:

#config.yml
    orm:
        dql:
            numeric_functions:
                FLOOR: FrontBundle\DoctrineFunctions\FloorFunction

#FloorFunction.php
<?php
namespace MyBundle\DoctrineFunctions;

use \Doctrine\ORM\Query\AST\Functions\FunctionNode;
use \Doctrine\ORM\Query\Lexer;

class FloorFunction extends FunctionNode
{
    public $simpleArithmeticExpression;

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FLOOR(' . $sqlWalker->walkSimpleArithmeticExpression(
            $this->simpleArithmeticExpression
        ) . ')';
    }

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

$config = $em->getConfiguration();
$config->addCustomNumericFunction('FLOOR', 'MyBundle\DoctrineFunctions\FloorFunction');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM