I need to get all rows where DATE(a.when)
matches the string 2014-09-30
.
$builder = $this->em->createQueryBuilder();
$builder->select('a')
->from('Entity\Appointment', 'a')
->andWhere('a.when = :date')
->setParameter('date', $date);
a.when
is a full DATETIME
; :date
is only a string
(in DATE
format).
The following and variations didn't work:
->andWhere('DATE(a.when) = :date')
Error: Expected known function, got 'DATE'
What's the correct usage here?
This actually is a very common question.
It turns out that not all sql databases support a DATE function, so the good people in charge of Doctrine decided not to support it nativelly.
Kind of wish they did because it would have saved a bunch of people a fair amount of effort.
So add this rather magical class to your project:
namespace Cerad\Bundle\CoreBundle\Doctrine\DQL;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
class Date extends FunctionNode
{
public $date;
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return "DATE(" . $sqlWalker->walkArithmeticPrimary($this->date) . ")";
}
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->date = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
Then wire it up in the doctrine section of your app/config.yml:
doctrine:
orm:
default_entity_manager: default
auto_generate_proxy_classes: %kernel.debug%
entity_managers:
default:
connection: default
...
dql:
datetime_functions:
date: Cerad\Bundle\CoreBundle\Doctrine\DQL\Date
http://doctrine-orm.readthedocs.org/en/latest/cookbook/dql-user-defined-functions.html
http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html
http://symfony.com/doc/current/reference/configuration/doctrine.html
There are other bundles out there with more sql functions. Oddly enough, the first time I looked a few years ago, none of them had Date defined. So I just made my own.
====================================================================
Update 01
I did not check the tags carefully and assumed that this was a Symfony 2 application. The Date class stays the same. You wire it up by getting the doctrine configuration object.
$config = new \Doctrine\ORM\Configuration();
$config->addCustomDatetimeFunction('DATE', 'blahblah\Date');
Check the Doctrine link for details.
Thanks to andy, using this now:
$builder = $this->em->createQueryBuilder();
$builder->select('a')
->from('Entity\Appointment', 'a')
->andWhere('a.when >= :date_start')
->andWhere('a.when <= :date_end')
->setParameter('date_start', $date->format('Y-m-d 00:00:00'))
->setParameter('date_end', $date->format('Y-m-d 23:59:59'));