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 中对表达式中的值进行排序.
小智 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)
| 归档时间: |
|
| 查看次数: |
15343 次 |
| 最近记录: |