2013-09-30 16 views
11

Używam Symfony 2 i Doktryny ORM. Chcę utworzyć i zarejestrować niestandardową funkcję DQL. W rzeczywistości, chcę użyć funkcji SQL "CAST" na moją prośbę, tak:Błąd podczas używania niestandardowej funkcji DQL z Doctrine i Symfony2

$qb = $this->_em->createQueryBuilder(); 
    $qb->select('d') 
     ->from('\Test\MyBundle\Entity\MyEntity', 'd') 
     ->orderBy('CAST(d.myField AS UNSIGNED)', 'ASC') 

    return $qb->getQuery()->getResult(); 

za to, że stworzył "CastFunction" kto przedłużyć "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)); 
    } 
} 

Oczywiście, mam zarejestrowany tej klasy w moim config.yml:

doctrine: 
    orm: 
     dql: 
      string_functions: 
       CAST: Test\MyBundle\DQL\CastFunction 

Teraz, gdy próbuję moją prośbę, mogę uzyskać następujący błąd:

"[Błąd semantyczny] wiersz 0, kol. 83 w pobliżu" NIEZNANY) ": Błąd:" NIEZNANY "nie jest zdefiniowany."

Szukam, ale nie wiem, gdzie jest problem!

Masz pomysł?

Odpowiedz

10

Po kilku przeszukaniach znalazłem rozwiązanie. Miałem dwa problemy: najpierw funkcja parse była błędna, po drugie, nazwałem funkcję SQL w moim orderBy (dziękuję Cerad).

Tak, tu jest moja prawidłowa klasa:

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); 
    } 
} 

A teraz, mogę doskonale korzystać z funkcji SQL 'Cast' w moim repozytorium:

$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(); 

pozdrowieniami

+1

W jaki sposób uzyskałeś dostęp do właściwości "sortx" przez obiekt? – hardik

2

Nie można znaleźć odwołania, ale funkcje nie są dozwolone w klauzuli kolejność. Musisz rzucić swoją wartość w instrukcji select, a następnie sortuj według niej.

Coś jak:

$qb->select('d, CAST(d.myField AS UNSIGNED) AS sortx) 
    ->from('\Test\MyBundle\Entity\MyEntity', 'd') 
    ->orderBy('sortx, 'ASC') 

To jest zakładając swoją funkcję Cast jest napisane poprawnie.

+0

Dziękuję dla Twojej odpowiedzi. Ale już próbowałem tego kodu i problem utrzymuje się. Myślę, że problem pochodzi z funkcji "parsowania" klasy "CastFunction". Ale nie rozumiem, gdzie. – Scipius2012

Powiązane problemy