Doctrine 2 mysql FIELD function em ordem por

Eu estou tentando usar a function MySQL FIELD em uma ordem por cláusula em uma consulta. Estou assumindo que o Doctrine 2 não suporta a function FIELD fora da checkbox – isso é verdade? Se sim, como posso usá-lo? Terei que transformar minha consulta inteira em uma consulta nativa? Existe uma extensão do Doctrine 2 que adiciona essa funcionalidade?

Jeremy Hicks, obrigado pela sua extensão . Eu não sabia como conectar sua function à doctrine, mas finalmente encontrei resposta.

$doctrineConfig = $this->em->getConfiguration(); $doctrineConfig->addCustomStringFunction('FIELD', 'DoctrineExtensions\Query\Mysql\Field'); 

Eu preciso da function FIELD para ordenar minhas Entidades que eu seleciono pela expressão IN . Mas você pode usar essa function somente na cláusula SELECT, WHERE, BETWEEN , não em ORDER BY .

Solução:

 $qb ->select("r, field(r.id, " . implode(", ", $ids) . ") as HIDDEN field") ->from("Entities\Round", "r") ->where($qb->expr()->in("r.id", $ids)) ->orderBy("field"); 

Para evitar a adição de alias de field em sua linha de resultado, você precisa colocar a palavra-chave HIDDEN . Então, como poder ordenar valores na expressão IN no Doctrine 2.2.

Você pode adicionar suporte para a function DQL FIELD () mas, em vez disso, implementá-la como CASO SQL padrão. WHEN expression. Desta forma, sua function funcionaria tanto no MySQL quanto no Sqlite, o que é particularmente útil se você é como eu e gosta de executar seus testes de unidade em sqlite na memory.

Esta class é largamente baseada no trabalho de Jeremy Hicks (eu simplesmente mudei o método getSql ())

 class Field extends FunctionNode { private $field = null; private $values = array(); public function parse(\Doctrine\ORM\Query\Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); // Do the field. $this->field = $parser->ArithmeticPrimary(); // Add the strings to the values array. FIELD must // be used with at least 1 string not including the field. $lexer = $parser->getLexer(); while (count($this->values) < 1 || $lexer->lookahead['type'] != Lexer::T_CLOSE_PARENTHESIS) { $parser->match(Lexer::T_COMMA); $this->values[] = $parser->ArithmeticPrimary(); } $parser->match(Lexer::T_CLOSE_PARENTHESIS); } public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { $query = '(CASE ' . $this->field->dispatch($sqlWalker); for ($i=0, $limiti=count($this->values); $i < $limiti; $i++) { $query .= ' WHEN ' . $this->values[$i]->dispatch($sqlWalker) . ' THEN ' . $i; } $query .= ' END)'; return $query; } } 

Você pode escrever sua própria extensão DQL .

Caso o campo que você deseja “ordenar por” seja um tipo de dado ENUM, então ORDER BY funcionará na ordem em que os valores foram definidos para esse campo ENUM.

Por exemplo, eu tinha um arquivo definido como enum('n','pe','o','ap','c') que estava dando uma ordem estranha. A ordenação foi corrigida após atualizar o enum para: enum('ap','c','n','o','pe')