Формула виділення тексту або пошук як в Google.

Як правило, кожен автор сайту намагається зробити дизайн сайту і його функціональність як можна унікальний. Це стосується як комерційних сайтів так і домашніх сторіночок. Усе спрямовано на те, щоб привернути увагу відвідувача сайту не лише тематикою, а й зручною навігацією в морі інформації.

Кількість інформації постійно збільшується, а бажання відвідувача витрачати свій час і гроші на безплідні пошуки що його цікавить, зменшуються з кожним невдалим результатом пошуку та відвідуванням черговий непотрібної посилання.

Найбільш красиво вирішили це завдання автори всесвітньо відомого пошуковика "google", Де у висновку результатів пошуку виділяються необхідні ключові слова. Що служить декільком цілям, з одного боку показує користувачеві, що даний рядок була включена в результат пошуку саме тому, що знайдено відповідність, а головне відвідувачу легше орієнтуватися. Не витрачаючи даремно часу на аналіз виводу, де ж те, що я шукав і чому виведено те, що мені не потрібно.

Завдання стає особливо актуальною якщо, наприклад, вам необхідно провести пошук в таблиці, за кількома стовпцями одночасно, і результатом пошуку буде відповідно все та ж таблиця. У такій ситуації буде набагато зручніше переглядати вже заздалегідь виділений текст, а не виглядати його самостійно в кожному стовпчику.

Ця стаття і описує те, як написати свою функцію виділення знайденого – Шуканого тексту. І не просто виділити знайдений текст кольором, А укласти його в певні теги. Тобто самим вирішувати, що саме з ним робити. Виділити слово або його частину кольором, жирним шрифтом або підкресленим і т.д. Це вже залежить від фантазії розробника.

Отже сам код:

Скористаємося найпотужнішим інструментом пошуку та заміни – регулярними виразами.

Створюємо два масиви: $search – Що шукаємо і $replace – На що замінюємо.

$ Searchquery – ключі пошуку, розділені пробілами.

$search  = array(

"/ \ \ \ \ /", / / – 1

"/ ([Rn]) [s ]+/", / / – 2

"/ S *(.+) s * /", / / – 3

        );

$replace = array(

"\", / /
— 1

         ”
", / /
— 2

"$ 1", / /
— 3

);

Детальний опис роботи з регулярними виразами в PHP виходить за рамки цієї статті. Тому обмежуся описом самої ідеї того, як буде генеруватися регулярний вираз з рядка запиту користувача, у полі пошуку.

Отже яким цілям служить кожен шаблон:

  1. Замінюємо повторювані backslash'і () На один екранований (\).
    Передбачається що magic_quotes=1 в php.ini або до рядка запиту була застосована функція addslashes ($searchquery) Якщо magic_quotes=0.
  2. Замінюємо пропуски, що повторюються, символи табуляції і переведення рядка одним пропуском.
  3. Вирізаємо результат двох попередніх замін, відкидаємо пробіли на початку і кінці рядка, якщо вони присутні звичайно.
    $ Sorted_regexp = preg_replace ($ search, $ replace, preg_quote ($ searchquery));

Загалом вже можна було б і використовувати отриманий результат замінюючи повторювані пробільні символи не одним пропуском "", а "|" тим самим отримавши готове регулярне вираження сформоване з ключів пошуку. Якщо б не факти непомітні на перший погляд.

А саме: ніхто не заважає користувачеві ввести кілька ідентичних ключів пошуку, і навіщо їх "тягати" за собою або забороняти вводити? Але це не головне, головне те, що сгенерированное регулярний вираз і відповідно виділення тексту, працювати щось буде, але не так як очікується. Справа в тому, що при такому методі генерації регулярного виразу (шаблону для пошуку та виділення) є істотний недолік складається в тому, що пошук і виділення за таким шаблоном залежить від того в якому порядку розташовані і якої довжини ключові слова пошуку.

Наприклад, якщо відвідувачеві або адміністратора сайту захочеться зробити пошук по email'Ам то при введенні запиту в такій послідовності “@ @list.ru” (Припустимо, що шукані ключі знаходяться в таблиці), то будуть виділені всі символи @, але при цьому не виділиться list.ru. Так як одиночний символ @ стоїть першим то і в регулярному виразі він виявиться також першим і при обробці тексту задовольнить умові пошуку до "@ list.ru".

Усунемо описаний вище недолік вчинивши, потім, наступні дії:

  1. Видалимо дублюються ключі пошуку (якщо вони є).
  2. Відсортуємо ключі пошуку в порядку убування – що і виправить недолік.

Надалі знадобиться відсортувати значення масиву за їх довжиною в порядку убування.

Наступна функція допоможе в цьому:

<?

/ / === Сортування значень масиву по довжині в порядку убування.

/ / === Використовується спільно з usort

function sort_by_length ($ cur_val, $ next_val) {

    $cur=strlen($cur_val);

    $next=strlen($next_val);

    if ($cur==$next) return 0;

    return ($cur<$next)?-1:1;

    }

/ / === Масив в який занесемо ключі пошуку – для подальшої сортування

    $sorted_regexp_array=array();

/ / Змінна $ sorted_regexp – містить результат роботи preg_replace (див. вище).

/ / === Заносимо ключі пошуку в масив $ sorted_regexp_array

$ Sorted_regexp_array = preg_split ("/ s + /", $ sorted_regexp);

/ / === Видаляємо дублюються значення в масиві

$ Sorted_regexp_array = array_unique ($ sorted_regexp_array);

/ / === Сортуємо масив $ sorted_regexp_array в порядку убування

/ / === Функція rev_sort_by_length – наведена вище.

usort ($ sorted_regexp_array, "rev_sort_by_length");

/ / === Об'єднуємо відсортовані значення масиву в рядок.

$ Searchquery_regexp = implode ("|", $ sorted_regexp_array);

/ / === Укладаємо результат у круглі дужки – групуємо наш REGEXP

$ Searchquery_regexp = preg_replace ("/.+/","($ 0) ", $ searchquery_regexp);

?>

Таким чином, якщо змінна $searchquery містила рядок “@ @list.ru”, То після виконання описаних вище дій $searchquery_regexp буде містити рядок наступного виду "(@ list.ru |@)".

Сгенерированное регулярний вираз міститься в $searchquery_regexp готове до подальшого використання. Наприклад наступним чином:

$ String_to_output = preg_replace (! $ Searchquery_regexp! I, "<SPAN
STYLE=’background-color: #FFFF00;’>$0</SPAN>”,
$string_where_search);

Зверніть увагу на те що шаблон пошуку укладений не у /, а в! – Інакше буде видане повідомлення про помилку.

Все, якщо у змінній $string_where_search містить рядок буде знайдено відповідність одному з ключів пошуку – ділянка рядки або слова буде укладено (в даному випадку) в тег інакше рядок залишиться без змін.

Якщо використовуємо шаблони (Smatry Templates):

<?

{$ String_where_search | regex_replace: "! $ Searchquery_regexp! I": "<SPAN STYLE='background-color: #FFFF00;'> $ 0 </ SPAN>"}

?>

Таким чином, при пошуку в таблиці за кількома стовпцями, можна призначити кожному стовпцю свій стиль (колір) виділення. Наприклад: всі знайдені відповідності пошуку в першій колонці виділяти жирним шрифтом, А всі відповідності у другій колонці синім кольором і т.д. Хоч по часу доби змінювати колір або шрифт знайдених значень.

ЗАУВАЖЕННЯ:

Виділення є язикозавісімим. Тобто якщо в рядку пошуку буде введений символ "a" в російській розкладці то виділені будуть тільки російські символи "a". І відповідно якщо рядок пошуку введена в англійській розкладці виділені будуть тільки англійські символи. Цим можна скористатися там де необхідно багатомовне виділення.
Також при пошуку в російськомовному тексті враховується регістр. Тобто якщо в тексті є "a" і "A" і ключем пошуку був заданий символ "a" (в російській розкладці), то будуть виділені всі "a", але не "A".
Тобто пошук чутливий до регістру не дивлячись на прапор i. Це зауваження не відноситься до англомовного тексту.

Збираємо все в функцію:

<?

function sort_by_length ($cur_val, $next_val) {

    $cur=strlen($cur_val);

    $next=strlen($next_val);

    if ($cur==$next) return 0;

    return ($cur<$next)?-1:1;

}

function generate_regexp_from_query ($ searchquery, $ search = "", $ replace = "") {

    $search  = trim($search);

    $replace = trim($replace);

    if (empty($search) || empty($replace)) {

    $search  = array(

"/ \ \ \ \ /",

"/ ([Rn]) [s ]+/",

"/ S *(.+) s * /",

);

    $replace = array(

"\",

"",

"$ 1",

);

    }

$ Sorted_regexp = preg_replace ($ search, $ replace, preg_quote ($ searchquery));

    $sorted_regexp_array = array();

$ Sorted_regexp_array = preg_split ("/ s + /", $ sorted_regexp);

$ Sorted_regexp_array = array_unique ($ sorted_regexp_array);

usort ($ sorted_regexp_array, "rev_sort_by_length");

$ Searchquery_regexp = implode ("|", $ sorted_regexp_array);

$ Searchquery_regexp = preg_replace ("/.+/","($ 0) ", $ searchquery_regexp);

    return $searchquery_regexp;

}

?>

Висновок:
Описаний приклад виділення тексту є більш гнучким інструментом виділення, ніж вбудована функція highlight_string в якій немає свободи вибору. Що саме по собі неприємно. Набагато цікавіше, коли можливості обмежуються лише фантазією і не доводиться щоразу вигадувати велосипед. А витрачати дорогоцінний час на творчість.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*