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

时间:2011-09-13 16:35:35

标签: casting doctrine-orm type-conversion dql

我正在尝试获取 Doctrine2实体,按其ID排序,显然是一个字符串,即使它只包含Numbers。 所以我想做的是这样的事情:

SELECT entity1, cast (entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity 
ORDER BY orderId

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


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

7 个答案:

答案 0 :(得分:24)

您应该能够add your own function来实现此功能。

该课程看起来像这样:

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

您需要注册您的功能:

$config = $em->getConfiguration();
$config->addCustomNumericFunction('INT', 'MyProject\Query\CastAsInteger');

然后你可以使用它:

SELECT e, INT(e.id) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId

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

答案 1 :(得分: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);
    }
}

现在应该可以像这样编写DQL:

SELECT e, CAST(e.id AS integer) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId

答案 2 :(得分:3)

尝试此操作而不更改数据类型

  select (entity1 * 1) as display_value, entity1 as return_value 
      from Table_Name
     order by 1 asc;

答案 3 :(得分:0)

我认为您希望entity1订购。如果你的entity1数据类型是整数,那么不需要将它更改为整数,如果不是,那么你应该这样做。下面是你的查询。这个。

select entity1,cast(entity1 as integer) as order_id from Table_Name order by 1 asc;

答案 4 :(得分:0)

不确定这是否有效,但要访问实体ID,您需要IDENTITY()DQL函数。试试这个:

SELECT entity1  FROM Namespace\Bla\MyEntity  ORDER BY IDENTITY(entity1)

答案 5 :(得分:0)

在这种情况下,最好使用一些额外的功能(不要试图“规避”它们的功能)。例如。一个出色的解决方案是为Doctrine 2添加几乎所有必需的内容(盒子不支持)(DoctrineExtensions by beberlei)(github)。有了它,可以像在OP中一样直接使用CAST语句:

(“ Symfony示例”)例如在您的config.xml中添加行:

orm:
    ..
    entity_managers:
            ....
            dql:
                ....
                string_functions:
                    CAST: DoctrineExtensions\Query\Mysql\Cast

然后U可以像这样使用它:

 SELECT entity1, CAST(entity1.id AS integer) AS orderId
 FROM Namespace\Bla\MyEntity 
 ORDER BY orderId

答案 6 :(得分:-2)

我昨天在自己的代码中做了类似的事情。我能做到:

select cast(entity1 as int) as OrderID
from yourtablename
where yourconditions

我必须实际把我的钱当作金币然后是int,但是如果你没有小数,你就不应该有这个问题。您也可以尝试转换为数字或使用转换而不是强制转换,但在这种情况下强制转换。

如果OrderID中已经有相同的值,为什么需要entity1作为列?