doctrine2 and group_concat

后端 未结 2 1986
醉话见心
醉话见心 2021-01-06 06:42

i\'ve been looking through the docs/google and didn\'t find any solution.

is there any way to execute or imitate GROUP_CONCAT using doctrine2 (DQL) without native my

相关标签:
2条回答
  • 2021-01-06 06:52

    Yes this is possible with DoctrineExtensions from Beberlei (a core developer of Doctrine2). In doctrine2 you can define your own query expressions by extending the functionNode class.

    The easiest way is to include the DoctrineExtensions lib in your project. I don't know wether your are using Zend Framework or Symfony or any other framework so can't help you with embedding it.

    You can checkout DoctrineExtensions here:

    https://github.com/beberlei/DoctrineExtensions

    And the group function:

    https://github.com/beberlei/DoctrineExtensions/blob/master/src/Query/Mysql/GroupConcat.php

    Be aware you should use GroupConcat as function name not GROUP_CONCAT like in MySQL.

    Hope it helps you!

    0 讨论(0)
  • 2021-01-06 07:10

    Here is the full support version :

    // -------------------------------------------------
    // Complete support of GROUP_CONCAT in Doctrine2
    // -------------------------------------------------
    // Original Article: http://habrahabr.ru/post/181666/
    // Automated translation to English: http://sysmagazine.com/posts/181666/ 
    // Original github commit: https://github.com/denisvmedia/DoctrineExtensions/blob/d1caf21cd7c71cc557e60c26e9bf25323a194dd1/lib/DoctrineExtensions/Query/Mysql/GroupConcat.php
    
    /**
     * 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;
        }
    
    }
    
    // -------------------------------------------------
    // Example of usage:
    // -------------------------------------------------
    $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();
    
    0 讨论(0)
提交回复
热议问题