выделить несколько ключевых слов в поиске

Я использую этот код для выделения ключевых слов поиска:

function highlightWords($string, $word)
 {

        $string = str_replace($word, "<span class='highlight'>".$word."</span>", $string);
    /*** return the highlighted string ***/
    return $string;

 }

 ....

  $cQuote =  highlightWords(htmlspecialchars($row['cQuotes']), $search_result);

однако это выделяет только одно ключевое слово. если пользователь вводит более одного ключевого слова,это сужает поиск, но ни одно слово не выделяется. как я могу выделить более одного слова?

8 ответов


регулярные выражения-это путь!

function highlight($text, $words) {
    preg_match_all('~\w+~', $words, $m);
    if(!$m)
        return $text;
    $re = '~\b(' . implode('|', $m[0]) . ')\b~';
    return preg_replace($re, '<b></b>', $text);
}

$text = '
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
';

$words = 'ipsum labore';

print highlight($text, $words);

чтобы соответствовать без учета регистра, добавьте " i " в регулярное выражение

    $re = '~\b(' . implode('|', $m[0]) . ')\b~i';

примечание: для не-английский букв, как "ä", результаты могут варьироваться в зависимости от локали.


PHP > 5.3.0, попробуйте preg_filter ()

/**
 * Highlighting matching string
 * @param   string  $text           subject
 * @param   string  $words          search string
 * @return  string  highlighted text
 */
public function highlight($text, $words) {
    $highlighted = preg_filter('/' . preg_quote($words, '/') . '/i', '<b><span class="search-highlight"></span></b>', $text);
    if (!empty($highlighted)) {
        $text = $highlighted;
    }
    return $text;
}

предполагая, что слова вводятся как разделенная пробелом строка, вы можете просто использовать explode

$words = explode(' ', $term);

хотя, если вы хотите убедиться, что нет нескольких пробелов, вы можете сначала удалить их из строки

$term = preg_replace('/\s+/', ' ', trim($term));
$words = explode(' ', $term);

затем вам нужно сгенерировать массив замены

$highlighted = array();
foreach ( $words as $word ){
    $highlighted[] = "<span class='highlight'>".$word."</span>"
}

затем

str_replace($words, $highlighted, $string);

так положить его togther

function highlightWords($string, $term){
    $term = preg_replace('/\s+/', ' ', trim($term));
    $words = explode(' ', $term);

    $highlighted = array();
    foreach ( $words as $word ){
        $highlighted[] = "<span class='highlight'>".$word."</span>"
    }

    return str_replace($words, $highlighted, $string);
}

здесь простая функция для выделения только текста соответствия.

function highlighter_text($text, $words)
{
    $split_words = explode( " " , $words );
    foreach($split_words as $word)
    {
        $color = "#e5e5e5";
        $text = preg_replace("|($word)|Ui" ,
            "<span style=\"background:".$color.";\"><b></b></span>" , $text );
    }
    return $text;
}

вызов функции


выделите несколько ключевых слов в поиске, включая umlauts

я использовал регулярное выражение, написанное раньше, и заменил \w С [A-Za-z0-9_äöüÄÖÜ]. Как вы видите, я добавил умляуты äöüÄÖÜ. Я также удалил \b так это будет соответствовать любой вид поиска.

пример

поиск по ключевому слову:
Су Шамп

текст:
Солнце сияет. шампунь

результат:
СуН блестящие ШампОО


код, который я использовал:

private function getSearchTermToBold($text, $words)
{
    preg_match_all('~[A-Za-z0-9_äöüÄÖÜ]+~', $words, $m);
    if (!$m)
        return $text;
    $re = '~(' . implode('|', $m[0]) . ')~i';
    return preg_replace($re, '<b></b>', $text);
}

как предложено user187291, просто измените следующий код, чтобы получить текст, выделенный желтым фоном.

 return preg_replace($re, '<SPAN style="BACKGROUND-COLOR: #ffff00"><b></b></SPAN>', $text); 

разбивает поисковый запрос на слова, затем выделяет каждое слово отдельно.

Это может сработать лучше, чтобы выполнить выделение в javascript, хотя. селектор" содержит " jQuery, вероятно, поможет избежать проблем с заменой элементов разметки по мере продвижения...

http://api.jquery.com/contains-selector/


другие решения могут быть нечувствительны к регистру при поиске терминов выделения, но не сохраняют свой случай исходной строки. Поэтому поиск "st "найдет" ST", но выделит его как" st", термин поиска.

Я использую следующий. Сначала он формирует массив replace, а затем использует str_replace () с параметрами массива, что позволяет избежать рекурсии.

function highlightStr($haystack, $needle, $highlightStyle) {

    if (strlen($highlightStyle) < 1 || strlen($haystack) < 1 || strlen($needle) < 1) {
       return $haystack;
    }

    preg_match_all("/$needle+/i", $haystack, $matches);

    $matches[0] = array_unique($matches[0]);

    if (is_array($matches[0]) && count($matches[0]) >= 1) {
        foreach ($matches[0] as $ii=>$match)
            $replace[$ii]="<span style='$highlightStyle'>$match</span>";

        $haystack = str_replace($matches[0], $replace, $haystack);
    }

    return $haystack;
}