Doctrine: how to add custom functions that take an optional parameter?

Following the official explanation, I want to create my own custom MySQL ROUND () function, which can take (optionally) another second argument.

Ok, I did this:

<?php
namespace HQF\Bundle\PizzasBundle\DQL;

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

class MysqlRound extends FunctionNode
{
    public $simpleArithmeticExpression;

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'ROUND(' . $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);
    }
}

But how to realize the fact that everything is ROUND(XX)in order, but ROUND(XX, YY)also ok?

+5
source share
2 answers

You need to declare the second argument and use Lexeras follows:

namespace HQF\Bundle\PizzasBundle\DQL;

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

class MysqlRound extends FunctionNode
{
    private $firstExpression = null;
    private $secondExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $lexer = $parser->getLexer();
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->firstExpression = $parser->ArithmeticPrimary();

        // parse second parameter if available
        if(Lexer::T_COMMA === $lexer->lookahead['type']){
            $parser->match(Lexer::T_COMMA);
            $this->secondExpression = $parser->ArithmeticPrimary();
        }

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        // use second parameter if parsed
        if (null !== $this->secondExpression){
            return 'ROUND(' 
                . $this->firstExpression->dispatch($sqlWalker)
                . ', '
                . $this->secondExpression->dispatch($sqlWalker)
                . ')';
        }

        return 'ROUND(' . $this->firstExpression->dispatch($sqlWalker) . ')';
    }
}

Edit

Doctrine2 . @beberlei . (IFELSE, IFNULL, NULLIF, COS, ACOS ..), (ROUND, GREATEST LEAST , , .)

+11

GREATEST https://raw.githubusercontent.com/rodgermd/mura-show.com/master/src/Rodger/GalleryBundle/DoctrineExtension/Greatest.php (c) rodgermd @github:

namespace Rodger\GalleryBundle\DoctrineExtension;

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


class Greatest extends Functions\FunctionNode {

  protected $firstExpression, $secondExpression;

  public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
  {
    return sprintf("GREATEST(%s, %s)", 
            $this->firstExpression->dispatch($sqlWalker), 
            $this->secondExpression->dispatch($sqlWalker));
  }

  public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER); // (2)
        $parser->match(Lexer::T_OPEN_PARENTHESIS); // (3)
        $this->firstExpression = $parser->ArithmeticPrimary(); // (4)
        $parser->match(Lexer::T_COMMA); // (5)
        $this->secondExpression = $parser->ArithmeticPrimary(); // (6)
        $parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3)
    }
}
+1

All Articles