2017-04-13 59 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