Ошибка при использовании пользовательской функции 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 написана правильно.