Сопоставление нечувствительных к ударению подстрок - PullRequest
2 голосов
/ 27 августа 2010

У меня есть функция поиска, которая получает данные из таблицы 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

Ответы [ 2 ]

5 голосов
/ 27 августа 2010

Вы можете использовать Нормализатор для нормализации строки до Форма нормализации KD (NFKD) , где символы разлагаются, поэтому Á (U + 00C1) разлагается на комбинацию буквы A (U + 0041) и знака объединения ́ (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))

Итак, полный метод:

private static function highlightTerm($str, $term) {
    $str = Normalizer::normalize($str, Normalizer::FORM_KD);
    $pattern = '/('.preg_replace('/\p{L}/u', '$0\p{Mn}?', preg_quote($term, '/')).')/ui';
    return preg_replace($pattern, '<strong>$0</strong>', htmlspecialchars($str));
}
1 голос
/ 19 октября 2010

использование 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

...