Ошибка при использовании пользовательской функции DQL с помощью Doctrine и Symfony2

Я использую Symfony 2 и ORM Doctrine. Я хочу создать и зарегистрировать пользовательскую функцию DQL. Фактически, я хочу использовать функцию SQL "CAST" в моем запросе, например:

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

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

Для этого я создал "CastFunction", которые расширяют "FunctionNode":

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 "не определен."

Я ищу, но не знаю, где проблема!

У вас есть идея?

Ответ 1

После нескольких поисков я наконец нашел решение. У меня было две проблемы: сначала моя функция синтаксического анализа была неправильной, во-вторых, я вызвал функцию 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();

С наилучшими пожеланиями

Ответ 2

Невозможно найти ссылку, но функции не разрешены в предложении order by. Вам нужно указать ваше значение в инструкции select, а затем отсортировать его.

Что-то вроде:

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

Это означает, что ваша функция CAST написана правильно.