使用latin basic搜索php,但使用diactrics返回结果

时间:2017-04-21 16:05:32

标签: php symfony utf-8 doctrine

我遇到了一个复杂的情况,我希望能朝着正确的方向前进。

我需要允许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é

的任何内容

2 个答案:

答案 0 :(得分:1)

前言:目前尚不清楚要搜索的数据是否已存在于数据库中,或者您是否只是利用了数据库具有字符比较逻辑这一事实。我将假设数据源是数据库。

您尝试搜索html的事实引发了一个问题,即您是否真的想要搜索HTML,或者实际上想要在HTML中搜索用户可见的文本并去除html标签(如果有一个变音符号怎么办?标签属性?如果一个单词被空<span>打破怎么办?它应该匹配吗?如果它被<br>打破了怎么办?)

MySQL具有字符集(如何编码字符)和 collat​​ions (如何比较字符)的概念

相关文件:

假设您的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)

注意:generalunicode排序规则的更快但不严格正确的版本 - 但如果你说土耳其语,即使这是错误的(参见:dotted uppercase i

我会将已解码的html保存在数据库中并搜索,以确保正确设置了排序规则。

  • 使用SHOW CREATE TABLE xxx确认表/列排序规则正确无误。手动更改(ALTER TABLE ...),或根据this answer使用学说注释&amp;使用doctrine迁移进行更新(并在SHOW CREATE TABLE后确认您的学说版本遵循整理)
  • 确认该原则为configured以使用utf8编码。

如果您只需要覆盖一个特定查询的排序规则(例如,您无权更改数据库结构,或者它将破坏其他代码):

  • 如果您需要映射到学说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页面上测试了我的查询。它工作得很好: enter image description here

或者如果你想留在MySql上,添加这个UDF:

https://github.com/mysqludf/lib_mysqludf_preg