嵌套DQL用户定义函数

时间:2013-01-24 15:39:28

标签: php symfony doctrine user-defined-functions dql

如果我在一次返回中返回自定义函数,它可以正常工作,但我想将其拆分为两个不同的用户自定义函数。

按照这里的例子:

这是我使用嵌套函数

的查询示例
SELECT *
FROM database
WHERE 
    FUNC_1(FUNC_2('field_name'),'constraint_default') = 
        FUNC_1(FUNC_2('value_entered'),'constraint_entered')

示例函数

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class BarFunction extends FunctionNode
{
    public $stringExpression = null;
    public $trimValueExpression = null;

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

        $this->stringExpression = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_COMMA);

        $this->trimValueExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_1(' .
            $this->stringExpression->dispatch($sqlWalker) . ',' .
            $this->trimValueExpression->dispatch($sqlWalker) .
            ')';
    }
}

现在FUNC_2非常靠近FUNC_1,但从未被调用,因为我认为FUNC_1会返回解析后的语法,这会删除FUNC_2所需的语法。

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class FooFunction extends FunctionNode
{
    public $stringExpression = null;

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

        $this->stringExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) .
        ')';
    }
}

现在我已经创建了一个有效的组合功能:

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class CombinedFunction extends FunctionNode
{
    public $stringExpression = null;
    public $trimValueExpression = null;

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

        $this->stringExpression = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_COMMA);

        $this->trimValueExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_1(FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) . '),' .
            $this->trimValueExpression->dispatch($sqlWalker) .
            ')';
    }
}

但是我想知道是否可以使用嵌套的两个独立函数而不是创建这个组合函数?

思想?

更新:

添加yml配置

doctrine:
    dbal:
        ...

    orm:        
        entity_managers:
            foo_manager:
                dql:
                    numeric_functions:
                        FUNC_1: Foo\Bundle\FooBundle\DQL\NumericFunction\BarFunction
                        FUNC_2: Foo\Bundle\FooBundle\DQL\NumericFunction\FooFunction
                        COMB_FUNC: Foo\Bundle\FooBundle\DQL\NumericFunction\CombinedFunction

更新#2

所以FUNC_1会匹配这个

FUNC_1(value_of_func_2,'constraint_default')  

而FUNC_2会匹配此

FUNC_2('field_name')

1 个答案:

答案 0 :(得分:1)

我将FUNC_2定义为:

class FooFunction extends FunctionNode
{
    public $stringExpression = null;

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

        $this->stringExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) . ')';
    }
}

它为我生成了正确的sql:FUNC_1(FUNC_2(123),123)= FUNC_1(FUNC_2(123),123)