Полная поддержка GROUP_CONCAT в Doctrine2

от автора

Привет всем.

Так сложилось, что в проекте, над которым я сейчас работаю, потребовалось использовать функцию GROUP_CONCAT(). К сожалению, Doctrine2 «из коробки» эту функцию не поддерживает. Имеющееся же расширение от одного из разработчиков (Benjamin Eberlei) Doctrine2 значится как «limited support for GROUP_CONCAT». Понимаю, что использование данной функции автоматом ставит проект в зависимость от MySQL, но менять СУБД как перчатки не планируется. Так что оставим этот вопрос за рамками поста.

Поскольку погуглив я не нашел готового решения, решил написать его сам (взяв за основу разработку Benjamin’а). Комментировать там особо нечего, поэтому просто представляю его на суд общественности:

/**  * DoctrineExtensions Mysql Function Pack  *  * LICENSE  *  * This source file is subject to the new BSD license that is bundled  * with this package in the file LICENSE.txt.  * If you did not receive a copy of the license and are unable to  * obtain it through the world-wide-web, please send an email  * to kontakt@beberlei.de so I can send you a copy immediately.  */  namespace DoctrineExtensions\Query\Mysql;  use Doctrine\ORM\Query\AST\Functions\FunctionNode,     Doctrine\ORM\Query\Lexer;  /**  * Full support for:  *   * GROUP_CONCAT([DISTINCT] expr [,expr ...]  *              [ORDER BY {unsigned_integer | col_name | expr}  *                  [ASC | DESC] [,col_name ...]]  *              [SEPARATOR str_val])  *   */ class GroupConcat extends FunctionNode {     public $isDistinct = false;     public $pathExp = null;     public $separator = null;     public $orderBy = null;      public function parse(\Doctrine\ORM\Query\Parser $parser)     {         $parser->match(Lexer::T_IDENTIFIER);         $parser->match(Lexer::T_OPEN_PARENTHESIS);                  $lexer = $parser->getLexer();         if ($lexer->isNextToken(Lexer::T_DISTINCT)) {             $parser->match(Lexer::T_DISTINCT);                          $this->isDistinct = true;         }          // first Path Expression is mandatory         $this->pathExp = array();         $this->pathExp[] = $parser->SingleValuedPathExpression();          while ($lexer->isNextToken(Lexer::T_COMMA)) {             $parser->match(Lexer::T_COMMA);             $this->pathExp[] = $parser->StringPrimary();         }          if ($lexer->isNextToken(Lexer::T_ORDER)) {             $this->orderBy = $parser->OrderByClause();         }                  if ($lexer->isNextToken(Lexer::T_IDENTIFIER)) {             if (strtolower($lexer->lookahead['value']) !== 'separator') {                 $parser->syntaxError('separator');             }             $parser->match(Lexer::T_IDENTIFIER);                      $this->separator = $parser->StringPrimary();         }          $parser->match(Lexer::T_CLOSE_PARENTHESIS);     }      public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)     {         $result = 'GROUP_CONCAT(' . ($this->isDistinct ? 'DISTINCT ' : '');          $fields = array();         foreach ($this->pathExp as $pathExp) {             $fields[] = $pathExp->dispatch($sqlWalker);         }                  $result .= sprintf('%s', implode(', ', $fields));                  if ($this->orderBy) {             $result .= ' '.$sqlWalker->walkOrderByClause($this->orderBy);         }                  if ($this->separator) {             $result .= ' SEPARATOR '.$sqlWalker->walkStringPrimary($this->separator);         }                  $result .= ')';                  return $result;     }  } 

Пример использования:

$query = $this->createQueryBuilder('c')         ->select("             c as company,             GroupConcat(b.id, ';', b.headOffice, ';', b.city, ';', s.name             ORDER by b.id             SEPARATOR '|') AS branches         ")->leftJoin('c.branches','b')         ->leftJoin('b.country','s')         ->groupBy('c.id')         ->setFirstResult(0)         ->setMaxResults(10)         ->getQuery() ; $result = $query->getResult() 

Официальная документация по теме:
Регистрация пользовательских DQL функция в Doctrine2
Как подключить в пользовательские функции DQL в Symfony2.
Описание MySQL-функции GROUP_CONCAT

ссылка на оригинал статьи http://habrahabr.ru/post/181666/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *