Статья больше подходит для новичков.
Итак, задание! Сделать функцию ROUND, приступим:
Первое что нам нужно это сделать описание нашего метода через FunctionNode из Doctrine\ORM\Query\AST\Functions\FunctionNode.
Создадим в нашем Bundle папку с названием DQL (можно конечно обозвать как угодно).
У меня это выглядит так: src/Acme/SimpleBundle/DQL
Создаем в этой директории файл с названием например Round.php, получается src/Acme/SimpleBundle/DQL/Round.php
Содержимое:
namespace Acme\SimpleBundle\DQL; use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\AST\Functions\FunctionNode; class Round extends FunctionNode { protected $roundExp; protected $roundPrecission; public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { return 'ROUND(' . $sqlWalker->walkArithmeticExpression($this->roundExp) . ','. $sqlWalker->walkArithmeticExpression($this->roundPrecission) .')'; } /** * parse - allows DQL to breakdown the DQL string into a processable structure * @param \Doctrine\ORM\Query\Parser $parser */ public function parse(\Doctrine\ORM\Query\Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->roundExp = $parser->ArithmeticExpression(); // Указываем первое значение функции $parser->match(Lexer::T_COMMA); // Добавим разделитель $this->roundPrecission = $parser->ArithmeticExpression(); // И добавим второе значение $parser->match(Lexer::T_CLOSE_PARENTHESIS); } }
Нам нужно реализовать две функции, функция getSql как и ясно из названия вернет в ORM подготовленный SQL, а parse предназначена для парсинга переменных передаваемых в запрос, например round(sum,2)
Для того чтобы передавать параметры в функцию, нам необходимо определить внутренние переменные, в данном примере это:
protected $roundExp; protected $roundPrecission; // Чтобы было понятно то это выглядит так round(roundExp, roundPrecission)
Далее нам необходимо подсказать доктрине где искать наши функции, для этого укажем в config.yml в секции doctrine: что у нас есть дополнения к стандартному DQL, у меня это выглядит так:
doctrine: dbal: driver: %database_driver% host: %database_host% port: %database_port% dbname: %database_name% user: %database_user% password: %database_password% charset: UTF8 orm: auto_generate_proxy_classes: %kernel.debug% auto_mapping: true dql: string_functions: unix_timestamp: \Mart\AdminBundle\DQL\UnixTimestamp numeric_functions: round: \Mart\AdminBundle\DQL\Round
Теперь при выполнении запроса вида:
$queryBuilder->andWhere("ROUND (sum) , 1) = :condition");
Доктрина полезет в наши функции и составит правильный запрос в Mysql.
ссылка на оригинал статьи http://habrahabr.ru/post/209870/
Добавить комментарий