2017-04-13 26 views
0

我正在Symfony上編寫一個簡單的定製原則函數,它計算給定實體的bithdate的AGE。這裏是我的功能:Symfony Custom DoctrineFunctions總是返回null

class AgeFunction extends FunctionNode 
{ 
    private $birthDate; 

    public function parse(\Doctrine\ORM\Query\Parser $parser) 
    { 
     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 
     $this->birthDate = $parser->ArithmeticPrimary(); 
     $parser->match(Lexer::T_CLOSE_PARENTHESIS); 
    } 

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) 
    { 
     $bday = $this->birthDate->dispatch($sqlWalker); 
     $currDate = DateFormatter::formatDate(new \DateTime()); 

     return "TIMESTAMPDIFF(YEAR, {$bday}, '{$currDate}')"; 
    } 
} 

這裏是我如何使用它:

public function getAge() 
{ 
    $qb = $this->createQueryBuilder('s') 
     ->select('AGE(s.dateOfBirth)') 
     ->orderBy('s.id', 'DESC'); 

    dump($qb->getQuery()->getResult()); 
} 

這是產生的查詢:

SELECT TIMESTAMPDIFF(YEAR,s0_.date_of_birth,「2017 -04-13')AS sclr_0 FROM suspect s0_ ORDER BY s0_.id DESC;

我認爲這裏錯了什麼是s0_.date_of_birth從來沒有得到實際的價值,因爲當我手動將它取代它效果很好。

那麼我該如何做到這一點?謝謝。

+0

當您在sql客戶端(如phpmyadmin)中直接運行它時,生成的查詢是否顯示任何結果?我在我的一個數據庫中測試了它,查詢似乎是正確的。 –

+0

我有點好奇,爲什麼按照教條而不是php來處理年齡? – goto

回答

1

也許你最初試圖做別的事情,但業務需求似乎對我來說很奇怪,因爲你正在努力得到最後一個人的年齡。無論如何,讓我現在忽略它,並專注於你所需要的。我檢查了下面的例子,工作得很好。

DQL

namespace My\Bundle\Product\APIBundle\Entity\DQL; 

use Doctrine\ORM\Query\AST\Functions\FunctionNode; 
use Doctrine\ORM\Query\Lexer; 
use Doctrine\ORM\Query\Parser; 
use Doctrine\ORM\Query\SqlWalker; 

class TimestampDiff extends FunctionNode 
{ 
    public $value; 

    public function parse(Parser $parser) 
    { 
     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 
     $this->value = $parser->StringPrimary(); 
     $parser->match(Lexer::T_CLOSE_PARENTHESIS); 
    } 

    public function getSql(SqlWalker $sqlWalker) 
    { 
     return sprintf(
      'TIMESTAMPDIFF(YEAR, %s, %s)', 
      $this->value->dispatch($sqlWalker), 
      date('Y-m-d') 
     ); 
    } 
} 

REPOSITORY

public function findAge() 
{ 
    $qb = $this->createQueryBuilder('s') 
     ->select('TIMESTAMPDIFF(s.dateOfBirth) AS Age') 
     ->orderBy('s.id', 'DESC') 
     ->setMaxResults(1); 

    return $qb->getQuery()->getResult(Query::HYDRATE_SIMPLEOBJECT); 
} 

CALL

$p = $this->suspectRepository->findAge(); 

RE GISTER(我的設置是不同的,所以你可以檢查下面的鏈接,使之成爲您的安裝工作)

# app/config.yml 

doctrine: 
    dbal: 
     default_connection: hello 
     connections: 
     hello: 
      driver: "%database_driver%" 
      host: "%database_host%" 
      .... 
     .... 
    orm: 
     default_entity_manager: hello 

     entity_managers: 
      hello: 
       dql: 
        string_functions: 
         TIMESTAMPDIFF: My\Bundle\Product\APIBundle\Entity\DQL\TimestampDiff 
       connection: hello 
       .... 

結果

SELECT 
TIMESTAMPDIFF(YEAR, s0_.date_of_birth, 2017-04-13) AS sclr_0 
FROM suspect s0_ 
ORDER BY s0_.id DESC 
LIMIT 1 
+0

我會稍後再做,並回到你的結果:)謝謝。 – iamjc015

+0

無論如何,getAge()函數僅僅是一個測試在其他函數上使用DoctrineFunction。 – iamjc015