我有一个搜索功能,可以从InnoDB表(utf8_spanish_ci
排序规则)中获取数据并将其显示在HTML文档(UTF-8
字符集)中。用户键入子字符串并获得突出显示第一个子字符串出现的匹配列表,例如:
Matches for "AL":
Álava
<strong>Al</strong>bacete
<strong>Al</strong>mería
Ciudad Re<strong>al</strong>
Málaga
从示例中可以看出,搜索忽略了大小写和重音差异(MySQL会自动处理它)。但是,我用于高亮匹配的代码无法执行后者:
<?php
private static function highlightTerm($full_string, $match){
$start = mb_stripos($full_string, $match);
$length = mb_strlen($match);
return
htmlspecialchars( mb_substr($full_string, 0, $start)) .
'<strong>' . htmlspecialchars( mb_substr($full_string, $start, $length) ) . '</strong>' .
htmlspecialchars( mb_substr($full_string, $start+$length) );
}
?>
是否有一种合理的解决方法,并不意味着对所有可能的变化进行硬编码?
更新:系统规格为PHP / 5.2.14和MySQL / 5.1.48
答案 0 :(得分:5)
您可以使用Normalizer将字符串规范化为Normalization Form KD (NFKD),其中字符将被分解,因此Á
(U + 00C1)将被分解为字母组合{ {1}}(U + 0041)和组合标记A
(U + 0301):
́
然后修改搜索模式以匹配这些可选标记:
$str = Normalizer::normalize($str, Normalizer::FORM_KD);
然后使用$pattern = '/('.preg_replace('/\p{L}/u', '$0\p{Mn}?', preg_quote($term, '/')).')/ui';
preg_replace
所以完整的方法是:
preg_replace($pattern, '<strong>$0</strong>', htmlspecialchars($str))
答案 1 :(得分:1)
使用 PEAR I18N_UnicodeNormalizer-1.0.0
include('…');
echo preg_replace(
'/(\P{L})/ui', // replace all except members of Unicode class "letters", case insensitive
'', // with nothing → drop accents
I18N_UnicodeNormalizer::toNFKD('ÅÉÏÔÙåéïôù') // ù → u + `
);
→AEIOUaeiou