在 Doctrine DQL 查询中使用 COLLATE (Symfony2)

问题描述 投票:0回答:2

我找不到与在 Doctrine 的 DQL 查询中使用 COLLATE 相关的任何内容(当然它似乎不起作用)。

我的具体问题:

我有一张带有

utf8_general_ci
字符集的表格。我其中有一个特定字段,其中包含重音字符(如“á”、“ű”、“ő”等)

utf8_general_ci
的基本比较无法确定常规字符及其重音对(a = á,u = ű,o = ő)之间的差异,这对我来说对于大多数登陆的查询来说是完全可以的在那张桌子上!所以,如果我有的话,我们可以说:

 col1 |  col2
------|-------
   1  | árvíz  
------|-------
   2  | arviz

此查询将返回两个结果:

SELECT * FROM `table` WHERE `col2` = 'arviz'

再次强调,对于大多数用例来说,这对我来说完全没问题!

但是有一个特定的功能,我需要确定差异,并且在常规 MySQL 中我可以使用:

SELECT * FROM `table` WHERE `col2` COLLATE utf8_bin = 'arviz'

这仅返回未重音的版本。

问题是,可以使用 Doctrine 的 createQuery (编写 dql)或查询构建器来完成类似的事情吗?

我想我已经阅读了所有相关文档,但找不到方法来做到这一点。有可能吗?

php symfony doctrine-orm dql
2个回答
15
投票

按照 Cerad 的建议编写自定义 DQL 函数: http://www.doctrine-project.org/2010/03/29/doctrine2-custom-dql-udfs.html

我成功地创建了这个:

namespace MyCompany\MyBundle\DQL;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;

class CollateFunction extends FunctionNode
{
    public $expressionToCollate = null;
    public $collation = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->expressionToCollate = $parser->StringPrimary();

        $parser->match(Lexer::T_COMMA);

        $parser->match(Lexer::T_IDENTIFIER);
        $lexer = $parser->getLexer();
        $this->collation = $lexer->token['value'];

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return sprintf( '%s COLLATE %s', $this->expressionToCollate->dispatch($sqlWalker), $this->collation );
    }
}

注册到 config.yml 时 (http://symfony.com/doc/current/cookbook/doctrine/custom_dql_functions.html) 这将查找具有两个参数的整理“函数”:一个字段和一个字符集(尚未检测到有效的字符集)。

工作方式类似于(用 DQL 编写)

COLLATE( field , collation ) 

并创建(在可运行的 MySQL 中)

`field` COLLATE collation 

当然排序规则应该是一个有效的字符集(如

utf8_bin
),否则你会得到一个MySQL错误。

我想有一个更简单的解决方案,但我只能将其创建为“函数”。至少问题解决了。


0
投票

如果您收到错误:升级到

Cannot use object of type Doctrine\Common\Lexer\Token as array
Symfony v6.4

然后你需要调整你的

CollateFunction

中的一行

来自:

$this->collation = $lexer->token['value'];

致:

$this->collation = $lexer->token->value;

© www.soinside.com 2019 - 2024. All rights reserved.