2014-09-23 14 views
7

Tôi cần nhận tất cả các hàng nơi DATE(a.when) khớp với chuỗi 2014-09-30.Sử dụng `DATE()` trong Trình theo dõi truy vấn của Doctrine

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

a.when là đầy đủ DATETIME; :date chỉ là string (ở định dạng DATE).

Sau đây và các biến thể không làm việc:

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

Error: Expected known function, got 'DATE' 

sử dụng chính xác ở đây là gì?

+0

thể trùng lặp của [Học thuyết 2 - Lọc kết quả theo phần ngày một lĩnh vực datetime của] (http://stackoverflow.com/questions/10824383/doctrine-2 -filter-results-by-a-datetime-fields-date-part) – andy

+0

@ không phải là bản sao. Tôi đang sử dụng ** queryBuilder ** và thông báo lỗi bằng cách sử dụng 'createQuery' và' queryBuilder' là giống nhau: 'Lỗi: Hàm đã biết dự kiến, có 'DATE''. – DanFromGermany

+1

Các erro là như nhau vì không có 'DATE()' trong DQL. Nếu bạn sử dụng mệnh đề WHERE từ bản sao được liên kết, cách tiếp cận của bạn cũng sẽ hoạt động. – andy

Trả lời

7

Đây thực sự là một câu hỏi rất phổ biến. Nó chỉ ra rằng không phải tất cả các cơ sở dữ liệu sql đều hỗ trợ chức năng DATE, vì vậy những người tốt phụ trách Doctrine quyết định không hỗ trợ nó nativelly.

Loại điều ước mà họ đã làm bởi vì nó có thể tiết kiệm cho một nhóm người một lượng công sức.

Vì vậy, thêm lớp thay vì huyền diệu này để dự án của bạn:

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

Sau đó dây nó lên trong phần thuyết của ứng dụng của bạn/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

Có các gói khác ở đó với nhiều chức năng sql hơn. Kỳ lạ thay, lần đầu tiên tôi nhìn một vài năm trước đây, không ai trong số họ đã xác định ngày. Vì vậy, tôi chỉ làm của riêng tôi.

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

cập nhật 01

tôi đã không kiểm tra các thẻ một cách cẩn thận và cho rằng đây là một ứng dụng Symfony 2. Lớp Date vẫn giữ nguyên. Bạn dây nó lên bằng cách nhận được các đối tượng cấu hình giáo lý.

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

Kiểm tra liên kết Doctrine để biết chi tiết.

+0

Tôi cung cấp cho bạn một upvote cho nỗ lực của bạn, tiếc là tôi không thể thay đổi libs cốt lõi của chúng tôi như Doctrine. Tôi đang đi với một cách không DQL bây giờ cho đến khi tôi tìm thấy một cách tốt hơn. – DanFromGermany

+0

Bạn không thay đổi thư viện cốt lõi. Bạn chỉ cần thêm một chức năng tùy chỉnh. Không có gì bên trong Doctrine đang được thay đổi. – Cerad

+0

Tôi không thể làm cho nó "có dây". Tôi không có tệp cấu hình này.Tôi đã thử với 'YEAR()', 'DAY()' và 'MONTH()' bây giờ bởi vì các tệp lớp của chúng đã có nhưng lỗi tương ứng với nhau .. – DanFromGermany

7

Nhờ andy, sử dụng này ngay bây giờ:

$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')); 
Các vấn đề liên quan