Use a DATE() function in a WHERE clause with DQL

Jurian Sluiman picture Jurian Sluiman · Nov 7, 2012 · Viewed 13.5k times · Source

I get a strange error when I execute this DQL query:

SELECT u FROM User u LEFT JOIN u.schedule s WHERE DATE(s.timestamp) = DATE(NOW())

The exception is thrown by Doctrine with the message:

Expected known function, got 'DATE'

The problem looks similar to this bug, but that addresses the DATE() function in a GROUP BY clause and the bug is closed for Doctrine 2.2. At this moment, I get the exception with doctrine 2.4-DEV.

The query is meant to select all users scheduled for today. Is there any way I can create this DQL? I tested the SQL version in phpMyAdmin and there the query does not raise an error. What might be wrong?

Answer

BenMorel picture BenMorel · Jan 7, 2013

You can achieve what you want by using a custom function:

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

class DateFunction extends FunctionNode
{
    private $arg;

    public function getSql(SqlWalker $sqlWalker)
    {
        return sprintf('DATE(%s)', $this->arg->dispatch($sqlWalker));
    }

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->arg = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

Then registering this function in your code:

$em->getConfiguration()->addCustomDatetimeFunction('DATE', 'DateFunction');

And your DQL query will work!