Reputation: 2245
I'm writing a simple Custom Doctrine Function on Symfony that computes AGE given the bithdate of the entity. Here is my function:
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}')";
}
}
And here is how i used it:
public function getAge()
{
$qb = $this->createQueryBuilder('s')
->select('AGE(s.dateOfBirth)')
->orderBy('s.id', 'DESC');
dump($qb->getQuery()->getResult());
}
This is the query produced:
SELECT TIMESTAMPDIFF(YEAR, s0_.date_of_birth, '2017-04-13') AS sclr_0 FROM suspect s0_ ORDER BY s0_.id DESC;
I think whats wrong here is s0_.date_of_birth never gets the actual value since when i replace it manually it works well.
So how can I do this? Thanks.
Upvotes: 0
Views: 229
Reputation: 12740
Maybe you're originally trying to do something else but the business requirement seems weird to me cos you're trying get just last person's age . Anyway let me just ignore it for now and focus on what you need. I've checked the example below and worked fine.
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();
REGISTER (My setup is different so you can check links below to make it work for your setup)
# 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
....
RESULT
SELECT
TIMESTAMPDIFF(YEAR, s0_.date_of_birth, 2017-04-13) AS sclr_0
FROM suspect s0_
ORDER BY s0_.id DESC
LIMIT 1
Upvotes: 1