我正在尝试在查询中的order by子句中使用MySQL FIELD函数。我假设Doctrine 2不支持开箱即用的FIELD功能 - 这是真的吗?如果是这样,我该如何使用它?我是否必须将整个查询转换为本机查询?是否有添加此功能的Doctrine 2扩展名?
答案 0 :(得分:23)
Jeremy Hicks,感谢your extension。 我不知道如何将你的功能与学说联系起来,但最后我找到了答案。
$doctrineConfig = $this->em->getConfiguration();
$doctrineConfig->addCustomStringFunction('FIELD', 'DoctrineExtensions\Query\Mysql\Field');
我需要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");
要避免在结果行中添加field
别名,您需要添加HIDDEN
个关键字。这就是如何在Doctrine 2.2中的IN
表达式中订购值。
答案 1 :(得分: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;
}
}
答案 2 :(得分:2)
您可以自己编写DQL extension。
答案 3 :(得分:0)
如果你想要的字段&#34;按顺序排列&#34;是ENUM数据类型,然后ORDER BY将按照为该ENUM字段定义值的顺序工作。
例如,我有一个定义为enum('n','pe','o','ap','c')
的字段给出了奇怪的排序。将枚举更新为enum('ap','c','n','o','pe')