Атрибуты CASTING для заказа в Doctrine2 DQL Query

Я пытаюсь получить Doctrine2 Entities, упорядоченный по их идентификатору, который, по-видимому, является строкой, хотя он содержит только числа. Итак, что бы я хотел сделать, это примерно так:

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

Есть ли способ сделать что-то подобное в Doctrine2? Или, что было бы лучшей практикой для получения моего результата, если я не могу изменить тип идентификатора (из-за требований клиента, конечно)?


Внимание: я не прошу код SQL, я прошу разрешения Doctrine2, желательно в DQL

Ответы

Ответ 1

Вы можете добавить свою собственную функцию для реализации этой функции.

Класс будет выглядеть примерно так:

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 не будет в результатах (и используется только для упорядочения).

Ответ 2

Основываясь на ответе Джаспера Н. Брауэра, это немного улучшенное решение:

<?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

Ответ 3

Попробуйте это, не изменив тип данных

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

Ответ 4

Я думаю, что вы хотите заказать entity1. если ваш тип данных entity1 является целым числом, тогда нет необходимости изменять его на целое число, или если это не так, вы должны это сделать. ниже запрос для you.try этот.

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

Ответ 5

Не уверен, что это работает, но для доступа к идентификатору объекта вам понадобится функция IDENTITY() DQL. Попробуйте следующее:

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

Ответ 6

Подумайте, лучше использовать некоторые дополнительные функции в таких случаях (не пытаясь "обойти" их). Например, отличным решением, добавляющим почти все необходимые (не поддерживаемые из коробки) материалы для Doctrine 2 является DoctrineExtensions от beberlei (github). С его помощью можно напрямую использовать CAST -statement, как в случае OP:

("Пример Symfony") Например, в вашем config.xml добавьте строки:

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

Тогда вы можете использовать его как:

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

Ответ 7

Я только что сделал что-то подобное в своем собственном коде вчера. Я смог:

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

Я должен был на самом деле лишить меня денег, а затем int, но если у вас нет десятичного числа, у вас не должно быть этой проблемы. Вы также можете попробовать кастинг как числовой или использовать convert вместо cast, но в этой ситуации лучше использовать cast.

Зачем вам нужна сущность1 в качестве столбца, если у вас уже есть такое же значение в OrderID?