问题 与Doctrine和Symfony2一起使用自定义DQL函数时出错


我使用Symfony 2和ORM Doctrine。我想创建并注册自定义DQL函数。实际上,我想使用SQL函数““在我的请求中,像这样:

    $qb = $this->_em->createQueryBuilder();
    $qb->select('d')
       ->from('\Test\MyBundle\Entity\MyEntity', 'd')
       ->orderBy('CAST(d.myField AS UNSIGNED)', 'ASC')

    return $qb->getQuery()->getResult();

为此,我创建了一个扩展“FunctionNode”的“CastFunction”:

namespace Test\MyBundle\DQL;

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

class CastFunction extends FunctionNode
{
    public $firstDateExpression = null;
    public $secondDateExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->firstDateExpression = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_IDENTIFIER);
        $this->secondDateExpression = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return sprintf('CAST(%s AS %s)', $this->firstDateExpression->dispatch($sqlWalker), $this->secondDateExpression->dispatch($sqlWalker));
    }
}

当然,我在config.yml中注册了这个类:

doctrine:
    orm:
        dql:
            string_functions:
                CAST: Test\MyBundle\DQL\CastFunction

现在,当我尝试我的请求时,我收到以下错误:

“[语义错误]第0行,第83行附近'UNSIGNED)':错误:未定义'UNSIGNED'。”

我搜索但我不知道问题在哪里!

你有个主意吗?


5788
2017-09-30 14:12


起源



答案:


经过几次搜索,我终于找到了解决方案。我有两个问题:首先我的解析函数是错误的,第二,我在我的订单中调用了一个SQL函数(谢谢 CERAD)。

所以,这是我正确的课程:

namespace Ypok\YPoliceBundle\DQL;

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

class CastFunction extends FunctionNode
{
    public $firstDateExpression = null;
    public $unit = null;    

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

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

        $parser->match(Lexer::T_IDENTIFIER);
        $lexer = $parser->getLexer();
        $this->unit = $lexer->token['value'];

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return sprintf('CAST(%s AS %s)',  $this->firstDateExpression->dispatch($sqlWalker), $this->unit);
    }
}

现在,我可以在我的存储库中完美地使用SQL函数'CAST':

$qb = $this->_em->createQueryBuilder();
$qb->select('d, CAST(d.myField AS UNSIGNED) AS sortx')
   ->from('\Test\MyBundle\Entity\MyEntity', 'd')
   ->orderBy('sortx', 'ASC')

return $qb->getQuery()->getResult();

最好的祝福


10
2017-10-01 09:29



你是如何通过对象访问“sortx”属性的? - hardik


答案:


经过几次搜索,我终于找到了解决方案。我有两个问题:首先我的解析函数是错误的,第二,我在我的订单中调用了一个SQL函数(谢谢 CERAD)。

所以,这是我正确的课程:

namespace Ypok\YPoliceBundle\DQL;

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

class CastFunction extends FunctionNode
{
    public $firstDateExpression = null;
    public $unit = null;    

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

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

        $parser->match(Lexer::T_IDENTIFIER);
        $lexer = $parser->getLexer();
        $this->unit = $lexer->token['value'];

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return sprintf('CAST(%s AS %s)',  $this->firstDateExpression->dispatch($sqlWalker), $this->unit);
    }
}

现在,我可以在我的存储库中完美地使用SQL函数'CAST':

$qb = $this->_em->createQueryBuilder();
$qb->select('d, CAST(d.myField AS UNSIGNED) AS sortx')
   ->from('\Test\MyBundle\Entity\MyEntity', 'd')
   ->orderBy('sortx', 'ASC')

return $qb->getQuery()->getResult();

最好的祝福


10
2017-10-01 09:29



你是如何通过对象访问“sortx”属性的? - hardik


找不到引用,但order by子句中不允许使用函数。您需要在select语句中转换值,然后按它排序。

就像是:

$qb->select('d, CAST(d.myField AS UNSIGNED) AS sortx)
   ->from('\Test\MyBundle\Entity\MyEntity', 'd')
   ->orderBy('sortx, 'ASC')

假设你的CAST函数写得正确。


2
2017-09-30 16:55



谢谢您的回答。但我已经尝试过这段代码并且问题仍然存在。我认为问题来自“CastFunction”类的“解析”功能。但我不明白在哪里。 - Scipius2012