Doctrine 2 mysql FIELD函数按顺序排列

Jer*_*cks 13 mysql field native doctrine-orm

我正在尝试在查询中的order by子句中使用MySQL FIELD函数.我假设Doctrine 2不支持开箱即用的FIELD功能 - 这是真的吗?如果是这样,我该如何使用它?我是否必须将整个查询转换为本机查询?是否有添加此功能的Doctrine 2扩展?

小智 23

杰里米希克斯,谢谢你的延期.我不知道如何将你的功能与学说联系起来,但最后我找到了答案.

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

我需要FIELD函数来命令我通过IN表达式选择的实体.但是你只能在SELECT, WHERE, BETWEEN子句中使用这个函数,而不是在ORDER BY.

解:

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

要避免field在结果行中添加别名,您需要使用put HIDDEN关键字.这就是如何IN在Doctrine 2.2 中对表达式中的值进行排序.

  • 你也可以简单地使用如下参数:` - > select("r,field(r.id,:ids)作为HIDDEN字段") - > from("Entities\Round","r") - > where(" r.id IN:ids") - > setParameter('ids',$ ids) - > orderBy("field");` (5认同)

小智 6

您可以添加对FIELD()DQL函数的支持,但是将其实现为标准SQL CASE .. WHEN表达式.这样你的函数就可以在MySQL和Sqlite上运行,如果你像我一样喜欢在内存中的sqlite上运行你的单元测试,这个特别有用.

这个课程主要基于Jeremy Hicks的工作(我只是更改了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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ond*_*tes 2

您可以编写自己的DQL 扩展