2013-03-25 26 views
6

Tôi biết từ tài liệu tại: http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html#dql-functions rằng không có hàm ROUND nhưng có cách nào dễ dàng để thực hiện điều đó mà không cần viết hàm lớp DQL của riêng tôi không?Doctrine 2 DQL MySQL tương đương với ROUND()?

Chỉnh sửa: Tôi sẽ không cần khớp chính xác nếu thực hiện trung bình và trả về một số nguyên là có thể.

Trả lời

6

Bạn cần triển khai custom DQL function cho điều đó.

Có một số ví dụ trong DoctrineExtensions.

Bạn có thể thực hiện nó như sau:

<?php 

namespace MyApp\DQL; 

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

class Round extends FunctionNode 
{ 
    private $arithmeticExpression; 

    public function getSql(SqlWalker $sqlWalker) 
    { 

     return 'ROUND(' . $sqlWalker->walkSimpleArithmeticExpression(
      $this->arithmeticExpression 
     ) . ')'; 
    } 

    public function parse(\Doctrine\ORM\Query\Parser $parser) 
    { 

     $lexer = $parser->getLexer(); 

     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 

     $this->arithmeticExpression = $parser->SimpleArithmeticExpression(); 

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

Sau đó, bạn có thể đăng ký nó trong cấu hình trong khi bootstrapping các ORM:

$config = new \Doctrine\ORM\Configuration(); 

$config->addCustomNumericFunction('ROUND', 'MyApp\DQL\Round'); 
+0

Có điều này có vẻ như cách duy nhất để làm điều đó. Tôi đánh giá cao các hướng dẫn. – Shawn

6

Một chút cách tiếp cận sạch sẽ sử dụng hơi đã sửa đổi mã @Ocramius.

Đặt đoạn mã này trong: src/YourNamespace/YourMainBundle/DoctrineFunctions/ thư mục như Round.php filename:

<?php 
namespace YourApp\YourMainBundle\DoctrineFunctions; 

use Doctrine\ORM\Query\AST\Functions\FunctionNode, 
    Doctrine\ORM\Query\Lexer; 

class Round extends FunctionNode 
{ 
    private $arithmeticExpression; 

    public function parse(\Doctrine\ORM\Query\Parser $parser) 
    { 

     $lexer = $parser->getLexer(); 

     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 

     $this->arithmeticExpression = $parser->SimpleArithmeticExpression(); 

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) 
    { 
     return 'ROUND(' . $sqlWalker->walkSimpleArithmeticExpression($this->arithmeticExpression) . ')'; 
    } 
} 

Sau đó đặt điều này trong app/config/config.yml của bạn:

doctrine: 
    dql: 
     numeric_functions: 
      round: YourApp\YourMainBundle\DoctrineFunctions\Round 

Điều đó sẽ cho phép bạn sử dụng ROUND() chức năng trực tiếp trong các truy vấn DQL SELECT của bạn; không có vấn đề gì nếu được thực hiện với QueryBuilder hoặc trực tiếp qua createQuery()

+2

Thx rất nhiều cho gợi ý nhưng cấu hình "dql" phải dưới "orm" (doctrine: orm: dql: ...). – ownking

3

Nếu bạn muốn có thể chỉ định độ chính xác làm tròn, bạn có thể sử dụng lớp được cung cấp here. Nếu bạn đang sử dụng symfony, hãy cài đặt gói, vì bạn cũng sẽ nhận được các hàm mysql tiêu chuẩn bổ sung.

Mã của tài nguyên liên kết cũng có sẵn dưới đây:

<?php 
namespace Mapado\MysqlDoctrineFunctions\DQL; 
use \Doctrine\ORM\Query\AST\Functions\FunctionNode; 
use \Doctrine\ORM\Query\Lexer; 
/** 
* MysqlRound 
* 
* @uses FunctionNode 
* @author Julien DENIAU <[email protected]> 
*/ 
class MysqlRound extends FunctionNode 
{ 
    /** 
    * simpleArithmeticExpression 
    * 
    * @var mixed 
    * @access public 
    */ 
    public $simpleArithmeticExpression; 
    /** 
    * roundPrecission 
    * 
    * @var mixed 
    * @access public 
    */ 
    public $roundPrecission; 
    /** 
    * getSql 
    * 
    * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker 
    * @access public 
    * @return string 
    */ 
    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) 
    { 
     return 'ROUND(' . 
       $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression) .','. 
       $sqlWalker->walkStringPrimary($this->roundPrecission) . 
     ')'; 
    } 
    /** 
    * parse 
    * 
    * @param \Doctrine\ORM\Query\Parser $parser 
    * @access public 
    * @return void 
    */ 
    public function parse(\Doctrine\ORM\Query\Parser $parser) 
    { 
     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 
     $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); 
     $parser->match(Lexer::T_COMMA); 
     $this->roundPrecission = $parser->ArithmeticExpression(); 
     if ($this->roundPrecission == null) { 
      $this->roundPrecission = 0; 
     } 
     $parser->match(Lexer::T_CLOSE_PARENTHESIS); 
    } 
} 
Các vấn đề liên quan