Doctrine2の完全なGROUP_CONCATサポート

みなさんこんにちは。



私が現在取り組んでいるプロジェクトでは、GROUP_CONCAT()関数を使用する必要がありました。 あいにく、Doctrine2はそのままではこの機能をサポートしていません。 Doctrine2開発者の1人(Benjamin Eberlei)からの既存の拡張は「GROUP_CONCATの限定サポート」としてリストされています。 この関数を使用すると、プロジェクトが自動的にMySQLに依存することを理解していますが、DBMSをグローブとして変更する予定はありません。 この質問を投稿の範囲外にしましょう。



グーグルで既製のソリューションを見つけられなかったので、私はそれを自分で書くことにしました(ベンジャミンの開発を基礎として)。 コメントする特別なものはありませんので、試用のために公開するだけです。



/** * 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();
      
      







トピックに関する公式ドキュメント:

Doctrine2にカスタムDQL関数を登録します

Symfony2でカスタムDQL関数に接続する方法

MySQL関数GROUP_CONCATの説明



All Articles