web-dev-qa-db-ja.com

Doctrine2DQLクエリで注文するためのCASTING属性

Doctrine2 Entitiesを取得しようとしています。これは、数字のみが含まれているにもかかわらず、明らかに文字列であるIDで並べ替えられています。だから私がやりたいのは次のようなものです:

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

Doctrine2でこのようなことをする方法はありますか?または、IDのタイプを変更できない場合(もちろん顧客の要件のために()、結果を取得するためのベストプラクティスは何でしょうか)?


注意:SQLコードを要求していません。できれば、DQLでDoctrine2ソリューションを要求しています。

20
Andresch Serj

独自の関数を追加 この機能を実装できるはずです。

クラスは次のようになります。

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は結果に含まれなくなります(注文にのみ使用されます)。

26

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
6
Petr

データ型を変更せずにこれを試してください

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

このような場合は、(それらを「回避」しようとせずに)追加の機能を使用する方がよいと考えてください。例えば。 Doctrine 2に必要な(ボックスからはサポートされていない)ほとんどすべてのものを追加する優れたソリューションは DoctrineExtensions by beberlei (github)です。これにより、OPの場合のように直接CASTステートメントを使用することができます。

( "symfony-example")例: 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
0
voodoo417

これが機能するかどうかはわかりませんが、エンティティIDにアクセスするには、IDENTITY()DQL関数が必要です。これを試して:

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

entity1で注文したいと思います。 entity1データ型が整数の場合は整数に変更する必要はありません。そうでない場合は変更する必要があります。以下はあなたへのクエリです。これを試してください。

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