在Doctrine2 DQL查询上进行排序的CASTING属性

And*_*erj 19 casting type-conversion dql doctrine-orm

我试图获得Doctrine2实体,按其ID排序,显然是一个字符串,即使它只包含数字.所以我想做的是这样的:

SELECT entity1, cast (entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity 
ORDER BY orderId
Run Code Online (Sandbox Code Playgroud)

有没有办法在Doctrine2中做这样的事情?或者,如果我无法更改ID的类型(当然是由于客户要求),获得我的结果的最佳做法是什么?


注意:我不是在问SQL代码,我要求一个Doctrine2解决方案,最好是在DQL中

Jas*_*wer 26

您应该能够添加自己的功能来实现此功能.

该类看起来像这样:

namespace MyProject\Query;

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

class CastAsInteger extends FunctionNode
{
    public $stringPrimary;

    public function getSql(SqlWalker $sqlWalker)
    {
        return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS integer)';
    }

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

        $this->stringPrimary = $parser->StringPrimary();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}
Run Code Online (Sandbox Code Playgroud)

你需要注册你的功能:

$config = $em->getConfiguration();
$config->addCustomNumericFunction('INT', 'MyProject\Query\CastAsInteger');
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它:

SELECT e, INT(e.id) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId
Run Code Online (Sandbox Code Playgroud)

PS:通过添加HIDDEN关键字,别名orderId将不在结果中(并且仅用于排序).


Pet*_*etr 6

根据Jasper N. Brouwer的回答,这是一个有点增强的解决方案:

<?php
namespace MyProject\Query;

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

class Cast extends FunctionNode
{
    /** @var \Doctrine\ORM\Query\AST\PathExpression */
    protected $first;
    /** @var string */
    protected $second;
    /**
     * @param SqlWalker $sqlWalker
     *
     * @return string
     */
    public function getSql(SqlWalker $sqlWalker)
    {
        return sprintf("CAST(%s AS %s)",
            $this->first->dispatch($sqlWalker),
            $this->second
            );
    }


    /**
     * @param Parser $parser
     *
     * @return void
     */
    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->first = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_AS);
        $parser->match(Lexer::T_IDENTIFIER);
        $this->second = $parser->getLexer()->token['value'];
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它应该像这样编写DQL:

SELECT e, CAST(e.id AS integer) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId
Run Code Online (Sandbox Code Playgroud)