7

公式の説明に従って、別の 2 番目の引数 (必須ではありません) を取ることができるカスタム MySQL 関数 ROUND() を作成したいと思います。

これまでのところ、私はこれを行いました:

<?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);
    }
}

ROUND(XX)しかし、OKであり、 OKでもあるという事実をどのように実装するのROUND(XX, YY)でしょうか?

4

2 に答える 2

13

Lexer2 番目の引数を宣言し、次のように使用する必要があります。

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) . ')';
    }
}

編集

多くの Doctrine2 拡張機能がここに書かれています。@beberlei の偉大な功績に感謝します。多くの関数が利用可能 ( IFELSEIFNULLNULLIFCOSACOSなど...) ですが、すべてではありません ( ROUNDGREATESTまたはLEAST不足していますが、必要に応じて自分で書くことができます)。

于 2013-02-26T12:55:12.170 に答える
2

ここにも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)
    }
}
于 2015-06-22T19:29:43.500 に答える