2014-09-23 10 views
7

Ho bisogno di ottenere tutte le righe dove DATE(a.when) corrisponde alla stringa 2014-09-30.Utilizzo di `DATE()` in Doctrine Querybuilder

$builder = $this->em->createQueryBuilder(); 
$builder->select('a') 
     ->from('Entity\Appointment', 'a') 
     ->andWhere('a.when = :date') 
     ->setParameter('date', $date); 

a.when è un full DATETIME; :date è solo un string (nel formato DATE).

Il seguente e le variazioni non ha funzionato:

 ->andWhere('DATE(a.when) = :date') 

Error: Expected known function, got 'DATE' 

Qual è il corretto utilizzo qui?

+0

possibile duplicato del [Dottrina 2 - Filtrare i risultati in parte la data di un campo datetime] (http://stackoverflow.com/questions/10824383/doctrine-2 -filter-results-by-a-datetime-fields-date-part) – andy

+0

@andy non è un duplicato. Sto usando ** queryBuilder ** e il messaggio di errore usando 'createQuery' e' queryBuilder' è lo stesso: 'Errore: funzione conosciuta prevista, ottenuto 'DATE''. – DanFromGermany

+1

L'erro è lo stesso perché non c'è 'DATE()' in DQL. Se usi la clausola WHERE dal duplicato collegato, anche il tuo approccio dovrebbe funzionare. – andy

risposta

7

Questa è davvero una domanda molto comune. Si scopre che non tutti i database sql supportano una funzione DATE, quindi le persone responsabili di Doctrine hanno deciso di non supportarlo in modo naturale.

Tipo di desiderio hanno fatto perché avrebbe salvato un sacco di persone una buona dose di sforzo.

Quindi aggiungere questa classe piuttosto magico per il vostro progetto:

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); 
    } 
} 

cablare in su nella sezione dottrina della tua 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

Esistono altri bundle con più funzioni sql. Stranamente, la prima volta che ho guardato alcuni anni fa, nessuno di loro aveva definito la data. Così ho appena fatto il mio.

========================================= ======================

Aggiornamento 01

non ho controllato le etichette con attenzione e pensato che questo era un applicazione Symfony 2. La classe Date rimane la stessa. Lo colleghi ottenendo l'oggetto di configurazione di dottrina.

$config = new \Doctrine\ORM\Configuration(); 
$config->addCustomDatetimeFunction('DATE', 'blahblah\Date'); 

Controllare il collegamento di Doctrine per i dettagli.

+0

Ti do un preventivo per il tuo impegno, sfortunatamente non posso cambiare le nostre librerie di base come Doctrine. Ora vado con un metodo non DQL finché non trovo un modo migliore. – DanFromGermany

+0

Non si sta modificando la libreria principale. Stai solo aggiungendo una funzione personalizzata. Nulla dentro Doctrine è stato modificato. – Cerad

+0

Non riesco a farlo "cablato". Non ho questo file di configurazione.Ho provato con 'YEAR()', 'DAY()' e 'MONTH()' ora perché i loro file di classe erano già lì ma l'errore è di conseguenza lo stesso .. – DanFromGermany

7

Grazie a Andy, che utilizzano questo ora:

$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')); 
Problemi correlati