我遇到了一个复杂的情况,我希望能朝着正确的方向前进。
我需要允许Basic Latin搜索以带有变音符号的结果。由于数据是用HTML而不是纯ASCII存储的,因此这一点变得更加复杂。我一直在取得一些进展,但遇到了两个问题。
首先:我可以使用以下内容将数据部分转换为有用的东西:
$string = 'Véra';
$converted = html_entity_decode($string, ENT_COMPAT, 'UTF-8');
setlocale(LC_ALL, 'en_US.UTF8');
$translit = iconv('UTF-8', 'ASCII//TRANSLIT', $converted);
echo $translit;
这会带来这个结果:V'era
这是一个开始,但我真正需要的是Vera
。我可以对结果字符串执行preg_replace,但有没有一种方法可以在没有连字符的情况下将其恢复?这只是一个例子;数据库中有更多的变音符号(例如ñ
等)。我觉得之前已经解决了这个问题(例如iconv returns strange results),但似乎没有列出任何解决方案。
更大的问题:我需要转换Vera
等字符串,并能够使用Véra
恢复结果。以及Vera
的结果。但是我相信我需要首先解决问题1才能达到这一点。
我在想像if($ translit){return $ string},但我有点不确定如何处理这个问题。
所有帮助表示赞赏。
编辑:我认为这可以直接在数据库中更容易完成,但是我遇到了DQL问题。我知道有一些方法可以在SQL中使用存储过程进行,但是对数据库的访问权限有限,我打开了在Doctrine中处理此问题的任何建议
好吧,也许我让这个太难了
我只需要一种方法来查找已在数据库中进行HTML编码的条目,而无需使用特定编码进行搜索,但也而不使用变音符本身。如果我搜索Jose
,则应在数据库中显示标记为José
答案 0 :(得分:1)
前言:目前尚不清楚要搜索的数据是否已存在于数据库中,或者您是否只是利用了数据库具有字符比较逻辑这一事实。我将假设数据源是数据库。
您尝试搜索html的事实引发了一个问题,即您是否真的想要搜索HTML,或者实际上想要在HTML中搜索用户可见的文本并去除html标签(如果有一个变音符号怎么办?标签属性?如果一个单词被空<span>
打破怎么办?它应该匹配吗?如果它被<br>
打破了怎么办?)
MySQL具有字符集(如何编码字符)和 collations (如何比较字符)的概念
相关文件:
假设您的mysql客户端/终端已正确设置为UTF8编码,则以下内容演示了覆盖排序规则的效果(使用ß作为特别有趣的示例)
> SET NAMES 'utf8';
> SELECT
'ß',
'ss',
'ß' = 'ss' COLLATE utf8_unicode_ci AS ss_unicode,
'ß' = 'ss' COLLATE utf8_general_ci AS ss_general,
'ß' = 's' COLLATE utf8_general_ci AS s_general;
+----+----+------------+------------+-----------+
| ß | ss | ss_unicode | ss_general | s_general |
+----+----+------------+------------+-----------+
| ß | ss | 1 | 0 | 1 |
+----+----+------------+------------+-----------+
1 row in set (0.00 sec)
注意:general
是unicode
排序规则的更快但不严格正确的版本 - 但如果你说土耳其语,即使这是错误的(参见:dotted uppercase i)
我会将已解码的html保存在数据库中并搜索,以确保正确设置了排序规则。
SHOW CREATE TABLE xxx
确认表/列排序规则正确无误。手动更改(ALTER TABLE ...
),或根据this answer使用学说注释&amp;使用doctrine迁移进行更新(并在SHOW CREATE TABLE
后确认您的学说版本遵循整理)如果您只需要覆盖一个特定查询的排序规则(例如,您无权更改数据库结构,或者它将破坏其他代码):
如果您需要映射到学说ORM对象,请按照上面的示例使用NativeQuery并添加COLLATE
覆盖。
如果您只想要记录ID&amp;然后,您可以使用直接query绕过带有COLLATE
覆盖的ORM
答案 1 :(得分:0)
您可以使用REGEX_REPLACE函数在请求时去除数据库中的diactrics。 Mysql数据库没有内置的regex_replace函数,但您可以使用用户定义的库,或将库更改为MariaDB。基于Mysql的MariaDB(将数据迁移到MariaDB很容易)。
然后在MariaDB中,您可以使用以下查询:
SELECT * FROM `test` WHERE 'jose' = REGEXP_REPLACE(name, '(&[A-Za-z]*;)', '')
// another variant with PHP variable
SELECT `table`.name FROM `table` WHERE $search = REGEXP_REPLACE(name, '(&[A-Za-z]*;)', '')
甚至phpMyAdmin也支持MariaDB。我在Demo页面上测试了我的查询。它工作得很好:
或者如果你想留在MySql上,添加这个UDF: