iamjc015
iamjc015

Reputation: 2245

Symfony Custom DoctrineFunctions always returns null

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

Answers (1)

BentCoder
BentCoder

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

Related Questions