Добрый день. Создал поиск на своем блоге. Поиск работает, но подсветка результатов поиска создать не удается. Ниже привожу выдержку кода с файла search.php. Вопрос: можно ли, опираясь на нижеследующий код, добавить код, который отвечает за подсветку результатов поиска? Если да, то как это можно реализовать? Буду благодарен за доступное и понятное объяснение! PHP: <?php require_once ('connectvars.php'); $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); // This function builds a search query from the search keywords and sort setting function build_query($user_search) { $search_query = "SELECT count(`id`) FROM `Blog_articles`" ; // Extract the search keywords into an array $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } // Generate a WHERE clause using all of the search keywords $where_list = array(); if (count($final_search_words) > 0) { foreach($final_search_words as $word) { $where_list[] = "text_introduction LIKE '%$word%'"; } } $where_clause = implode(' OR ', $where_list); // Add the keyword WHERE clause to the search query if (!empty($where_clause)) { $search_query .= " WHERE $where_clause "; } return $search_query; } function build_query1($user_search) { $search_query1 = "SELECT Ba.title, Ba.date, Ba.rubric_id, Ba.text_introduction, Ba.link, Rubrics.rubric, Rubrics.translit_rubric FROM Blog_articles AS Ba INNER JOIN Rubrics USING (rubric_id)" ; // Extract the search keywords into an array $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } // Generate a WHERE clause using all of the search keywords $where_list = array(); if (count($final_search_words) > 0) { foreach($final_search_words as $word) { $where_list[] = "Ba.text_introduction OR Ba.title LIKE '%$word%'"; } } $where_clause = implode(' OR ', $where_list); // Add the keyword WHERE clause to the search query if (!empty($where_clause)) { $search_query1 .= " WHERE $where_clause "; $search_query1 .= " ORDER BY Ba.title DESC LIMIT "; } return $search_query1; } $user_search = $_GET['usersearch']; //екранируем спецсимволы $user_search_ecran = quotemeta ($user_search); // Создаем строку для регулярного выражения $pattern = "/((?:^|>)[^<]*)(".$user_search_ecran.")/si"; // Подсвеченная строка $replace = '$1<b style="background:#FFFF00;">$2</b>'; // Заменяем $html = preg_replace($pattern, $replace, $html); $page = intval($_GET[page]); // значение текущей страницы из GET $num = 4; // Переменная хранит число сообщений выводимых на станице if ($page==0) $page=1; // Query to get the total results $query = build_query($user_search); $mysqli_result = mysqli_query($dbc, $query); if(mysqli_num_rows($mysqli_result)>0){ $count=mysqli_fetch_row($mysqli_result); } $posts = $count[0]; // получем значение кол-во всех записей // Находим общее число страниц $total = intval(($posts - 1) / $num) + 1; // Определяем начало сообщений для текущей страницы $page = intval($page); // Если значение $page меньше единицы или отрицательно // переходим на первую страницу // А если слишком большое, то переходим на последнюю if(empty($page) or $page < 0) $page = 1; if($page > $total) $page = $total; // Вычисляем начиная c какого номера // следует выводить сообщения $start = $page * $num - $num; // Проверяем нужны ли стрелки назад if ($page != 1) $pervpage = '<a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page=-1">Початок</a> <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 1).'"><</a> '; // Проверяем нужны ли стрелки вперед if ($page != $total) $nextpage = ' <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search . '&page='. ($page + 1).'">></a> <a href="' .$_SERVER['PHP_SELF'].'?usersearch=' . $user_search . '&page='.$total.'">Кінець</a> '; // Находим две ближайшие станицы с обоих краев, если они есть if($page - 2 > 0) $page2left = ' <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 2) .'">'. ($page - 2) .'</a> '; if($page - 1 > 0) $page1left = '<a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 1) .'">'. ($page - 1) .'</a> '; if($page + 2 <= $total) $page2right = ' <a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page + 2).'">'. ($page + 2) .'</a>'; if($page + 1 <= $total) $page1right = ' <a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page + 1).'">'. ($page + 1) .'</a>'; //получаем записи из БД (начиная с $start, кол-во записей = $num) $query = build_query1($user_search); $query .= "$start, $num"; $mysqli_result = mysqli_query($dbc, $query); if(mysqli_num_rows($mysqli_result)) { while ($row = mysqli_fetch_assoc($mysqli_result)) { ?> <div class="article"> <?php echo '<h3>' . '<a href="/' . $row['translit_rubric'] . '/' . $row['link'] . '">' . $row['title'] . '</a></h3>'; ?> <div class="info"> <div class="info-in"> <?php echo '<p> Рубрика: <a href="/' . $row['translit_rubric'] . '/' . $row['translit_rubric'] . '_index.php"> ' . $row['rubric'] . '</a> | ' . 'Автор <a href=' . "'../Avtor.php'>Дроботько Тарас</a> | " . substr($row['date'], 0, -3) . '</p>'; ?> </div> </div> <p class="indent"></p> <p class="indent"> <?php echo $row['text_introduction'] ?></p> <p class="continue">[<a href=" <?php echo '/' . $row['translit_rubric'] . '/' . $row['link'] ?>">Читати далі…</a>]</p> </div> <?php } } else { echo '<p class="text-info" style=" font-weight: bolder;">На ваш запит, на жаль, нічого не знайдено.</p>'; echo '<img src="img/Poshuk.jpg" class="img-responsive center-block" title="Пошук" alt="Пошук">'; } // если страниц больше чем одна if ($total>1) echo '<p><div align="center" class="navigation">' .$pervpage.$page2left.$page1left.'<span>'.$page.'</span>'.$page1right.$page2right .$nextpage.'</div></p>'; mysqli_close($dbc); ?>
Форум русскоязычный. При всём уважении к украинскому языку, переведи, чего тебе нужно --- Добавлено --- В том варианте, что ты привёл - прогонять результаты через mb_strpos после поиска, чтоб найти фрагмент, содержащий данное слово. Хотя, если есть возможность, я бы подключил sphinx, он, во-первых, быстрее будет искать, во-вторых, у него уже есть такая функция, насколько помнится
Пробовал в цикле while, передавая mb_strpos строки $row['text_introduction'] и $word. Не получилось. На что обратить внимание?
Нет. Пробовал вставить: PHP: if((mysqli_num_rows($mysqli_result)) ){ while ($row = mysqli_fetch_assoc($mysqli_result)) { if(mb_strpos($row['text_introduction'], $word)); '<b style="background:#FFFF00;">' . $word . '</b>'; ...
Можно так, и без strpos: https://stackoverflow.com/questions...word-in-the-string-if-it-contains-the-keyword, но обычно в результатах поиска не пихают весь текст, значит надо взять символов 100 до слова, символов 100 после текста, проверить, не обрезаешь ли ты слова, и к остатку применить регулярку из ссылки
Вроде просто, но в меня остается много вопросов. Не могли бы вы доработать файл, приведенный в начале, за вознаграждение? (Моя почта: drobotkot@gmail.com). Я бы проанализировал. Если нет, то куда могу обратиться?
Спасибо. Я проанализировал свой код. А также вставил и протестировал: PHP: $word = implode('|', build_word($user_search)); $text = preg_replace('%(?<=[^\p{L}\p{N}])('.str_replace('*', '[\p{L}\p{N}]*', $word).')(?=[^\p{L}\p{N}])(?=[^>]*<)%ui', '<span style="background: yellow;">$1</span>', '>'. $row['text_introduction'] .'<'); $text = substr($text, 1, -1); print_r($text); Вишеприведенный код будет работать когда вместо $row['text_introduction'] подставить конкретну строку. Но мне надо сделать подсветку слов в записи столбца 'text_introduction' таблицы mysql. А если Вы ознакомились с моим кодом, который в начале темы, то видели, что я использую цикл while, чтобы вивести нужную запись. Проблема в том, что циклу надо передать вишеупомянутые переменные ($word, $text). Иначе этот код не будет работать внутри цикла. Как можно решить данную проблемму?
Перед циклом собираем нужный шаблон: PHP: $w = "[\p{L}\p{N}]"; $pattern = "%(?<!$w)($word)(?!$w)%ui"; А в цикле находим конструкцию: PHP: echo $row['text_introduction'] И ставим вызов preg_replace(): PHP: echo preg_replace( $pattern, '<span style="background: yellow;">$1</span>', $row['text_introduction'] );
Огромное спасибо, Emilien!! С твоей помощью я научился делать подсветку на своем блоге! Слава Богу! Хотя код, приведенный Emilien, виделяет только 1 слово целиком, данный код можно доработать. Что я и сделал) Перед циклом вводил: PHP: $pattern_array = array(); $build = build_word($user_search); //Функция build_word($user_search) возвращает массив слов. $user_search - переменная, что содержит переданную строку, которая введена пользователем в форму. for($i=0; $i < (count(build_word($user_search))); $i++) // count определяет количество слов в массиве { $word= $build[$i]; $pattern = "/((?:^|>)[^<]*)(".$word.")/si"; // данный шаблон позволяет виводить слово, являющееся частю другого слова, независимо от регистра array_push($pattern_array, $pattern); //шаблон $pattern с нужным словом вставляем в массив $pattern_array } В цикле на месте конструкции PHP: echo$row['text_introduction'] я прописал: PHP: echo preg_replace( $pattern_array, '$1<span style="background: yellow;">$2</span>', $row['title'] ); Но искомый текст ( на кирилице ) остается регистрозависимим. Например, когда введу в форму "плагін", то выделение есть, а в случае "Плагін" - нет. Как можно решить данную проблему? Кодировка таблицы и столбца - utf8_general_ci.
Спасибо, применил. Тестируя поиск на своем блоге, заметил, что не все искомые слова и слоги подсвечиваются. Например, вводжу "ко" и получаю такую картинку (см. фото ниже). Пока не могу разобратся в чем дело. Анализирую. Буду очень благодарен, если поможете понять, в чем источник данного дефекта. Код с файла search.php додаю. PHP: <?php require_once ('connectvars.php'); $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); $user_search = $_GET['usersearch']; $user_search= quotemeta($user_search);//quotemeta — экранирует специальные символы function build_word($user_search) { // Extract the search keywords into an array $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } return $final_search_words; } // This function builds a search query from the search keywords and sort setting function build_query($user_search) { $search_query = "SELECT count(`id`) FROM `Blog_articles`" ; // Extract the search keywords into an array $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } // Generate a WHERE clause using all of the search keywords $where_list = array(); if (count($final_search_words) > 0) { foreach($final_search_words as $word) { $where_list[] = "text_introduction OR title LIKE '%$word%'"; } } $where_clause = implode(' OR ', $where_list); // Add the keyword WHERE clause to the search query if (!empty($where_clause)) { $search_query .= " WHERE $where_clause "; } return $search_query; } function build_query1($user_search) { $search_query1 = "SELECT Ba.title, Ba.date, Ba.rubric_id, Ba.text_introduction, Ba.link, Rubrics.rubric, Rubrics.translit_rubric FROM Blog_articles AS Ba INNER JOIN Rubrics USING (rubric_id)" ; // Extract the search keywords into an array $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } // Generate a WHERE clause using all of the search keywords $where_list = array(); if (count($final_search_words) > 0) { foreach($final_search_words as $word) { $where_list[] = "Ba.text_introduction OR Ba.title LIKE '%$word%'"; } } $where_clause = implode(' OR ', $where_list); // Add the keyword WHERE clause to the search query if (!empty($where_clause)) { $search_query1 .= " WHERE $where_clause "; $search_query1 .= " ORDER BY Ba.title DESC LIMIT "; } return $search_query1; } $page = intval($_GET[page]); // значение текущей страницы из GET $num = 3; // Переменная хранит число сообщений выводимых на станице if ($page==0) $page=1; // Query to get the total results $query = build_query($user_search); $mysqli_result = mysqli_query($dbc, $query); if(mysqli_num_rows($mysqli_result)>0){ $count=mysqli_fetch_row($mysqli_result); } $posts = $count[0]; // получем значение кол-во всех записей // Находим общее число страниц $total = intval(($posts - 1) / $num) + 1; // Определяем начало сообщений для текущей страницы $page = intval($page); // Если значение $page меньше единицы или отрицательно // переходим на первую страницу // А если слишком большое, то переходим на последнюю if(empty($page) or $page < 0) $page = 1; if($page > $total) $page = $total; // Вычисляем начиная c какого номера // следует выводить сообщения $start = $page * $num - $num; // Проверяем нужны ли стрелки назад if ($page != 1) $pervpage = '<a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page=-1">Початок</a> <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 1).'"><</a> '; // Проверяем нужны ли стрелки вперед if ($page != $total) $nextpage = ' <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search . '&page='. ($page + 1).'">></a> <a href="' .$_SERVER['PHP_SELF'].'?usersearch=' . $user_search . '&page='.$total.'">Кінець</a> '; // Находим две ближайшие станицы с обоих краев, если они есть if($page - 2 > 0) $page2left = ' <a href="' .$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 2) .'">'. ($page - 2) .'</a> '; if($page - 1 > 0) $page1left = '<a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page - 1) .'">'. ($page - 1) .'</a> '; if($page + 2 <= $total) $page2right = ' <a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page + 2).'">'. ($page + 2) .'</a>'; if($page + 1 <= $total) $page1right = ' <a href="'.$_SERVER['PHP_SELF']. '?usersearch=' . $user_search .'&page='. ($page + 1).'">'. ($page + 1) .'</a>'; //получаем записи из БД (начиная с $start, кол-во записей = $num) $query = build_query1($user_search); $query .= "$start, $num"; $mysqli_result = mysqli_query($dbc, $query); if(mysqli_num_rows($mysqli_result)){ $pattern_array = array(); $build = build_word($user_search); for($i=0; $i < (count(build_word($user_search))); $i++) { $word= $build[$i]; $pattern = "/((?:^|>)[^<]*)(".$word.")/ui"; array_push($pattern_array, $pattern); //шаблон $pattern с нужным словом вставляем в массив $pattern_array } while ($row = mysqli_fetch_assoc($mysqli_result)) { ?> <div class="article"> <?php echo '<h3>' . '<a href="/' . $row['translit_rubric'] . '/' . $row['link'] . '">'?> <?php echo preg_replace( $pattern_array, '$1<span style="background: yellow;">$2</span>', $row['title'] ); ?> <?php echo '</a></h3>'; ?> <div class="info"> <div class="info-in"> <?php echo '<p> Рубрика: <a href="/' . $row['translit_rubric'] . '/' . $row['translit_rubric'] . '_index.php"> ' . $row['rubric'] . '</a> | ' . 'Автор <a href=' . "'../Avtor.php'>Дроботько Тарас</a> | " . substr($row['date'], 0, -3) . '</p>'; ?> </div> </div> <p class="indent"></p> <p class="indent"> <?php echo preg_replace( $pattern_array, '$1<span style="background: yellow;">$2</span>', $row['text_introduction'] );?></p> <p class="continue">[<a href=" <?php echo '/' . $row['translit_rubric'] . '/' . $row['link'] ?>">Читати далі…</a>]</p> </div> <?php } } else { echo '<p class="text-info" style=" font-weight: bolder;">На ваш запит, на жаль, нічого не знайдено.</p>'; echo '<img src="img/Poshuk.jpg" class="img-responsive center-block" title="Пошук" alt="Пошук">'; } // если страниц больше чем одна if ($total>1) echo '<p><div align="center" class="navigation">' .$pervpage.$page2left.$page1left.'<span>'.$page.'</span>'.$page1right.$page2right .$nextpage.'</div></p>'; mysqli_close($dbc); ?>
PHP: "/((?:^|>)[^<]*)($word)/ui" Код (Text): [^<]* По умолчанию квантификаторы жадные и захватывают максимальное количество текста. Вот и находит только последнее слово. Добавление знака вопроса к квантификатору переключает его режим с жадного на ленивый. Тогда шаблон будет искать ближайшее совпадение и найдёт всё что нужно. PHP: "/((?:^|>)[^<]*?)($word)/ui"
Большое спасибо, Emilien. Хотя результатом работы предложенного тобой шаблона было виделение только 1 искомого слова (слога) в начале текста, где производился поиск. Но обнаружил, что, поскольку, в моем случае, текст с $row['title'] и $row['text_introduction'] не содержит html-разметки, где замена искомых слов на слова с тегами могла бы поломать разметку, то можно упростить шаблон: PHP: $pattern = "#(". $word . ")#ui"; А строку замены в preg_replace() на PHP: '<span style="background: yellow;">$1</span>' Заработало! Еще изменил в function build_query1($user_search) : PHP: $where_list[] = " ((Ba.title OR Ba.text_introduction LIKE '%$word%') OR (Ba.text_introduction OR Ba.title LIKE '%$word%')) "; И прописал в function build_query($user_search) то же самое, только без надстройки Ва (синоним названия таблицы mysql). Дело в том, что поиск не находил слов, которые были только в $row['text_introduction'], поскольку Ba.text_introduction стояло перед оператором OR. Етот дефект запросов mysql можно увидеть, если проанализивать мой код в предыдущих сообщениях. На данный момент работа поиска с подсветкой удовлетворяет меня.
Приветствую! У меня возник еще один вопрос, когда я пробовал применить релевантность к поиску с подсветкой. Пробовал вот так: PHP: function build_query1($user_search) { $clean_search = str_replace(',', ' ', $user_search); $search_words = explode(' ', $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word)) { $final_search_words[] = $word; } } } // Generate a WHERE clause using all of the search keywords $where_list = array(); $relevance = '0'; $count = 0; if (count($final_search_words) > 0) { foreach($final_search_words as $word) { if ($count++ > 4) break; $where_list[] = " ((Ba.title OR Ba.text_introduction LIKE '%$word%') OR (Ba.text_introduction OR Ba.title LIKE '%$word%')) "; $relevance .= ' + (((LENGTH(Ba.title) - LENGTH(REPLACE(Ba.title, "'.$word.'", ""))) / LENGTH("'.$word.'"))+((LENGTH(Ba.text_introduction) - LENGTH(REPLACE(Ba.text_introduction, "'.$word.'", ""))) / LENGTH("'.$word.'")))'; } $relevance .= ' as relevance'; } $search_query1 = "SELECT Ba.title, Ba.date, Ba.rubric_id, Ba.text_introduction, Ba.link, Rubrics.rubric, Rubrics.translit_rubric " . $relevance . " FROM Blog_articles AS Ba INNER JOIN Rubrics USING (rubric_id)" ; $where_clause = implode(' OR ', $where_list); //Add the keyword WHERE clause to the search query if (!empty($where_clause)) { $search_query1 .= " WHERE $where_clause "; $search_query1 .= " ORDER BY relevance DESC LIMIT "; } return $search_query1; } .... $query = build_query1($user_search); $query .= " $start, $num"; print_r($query); $mysqli_result = mysqli_query($dbc, $query); if(mysqli_num_rows($mysqli_result)){ .... В результате, при вводе слова "плагин" в форму, появлялось сообщение, что ничего не найдено (см. фото). Что не так с запросом к базе данных mysql, что нужно изменить в запросе? --- Добавлено --- Разобрался. Перед $relevance в запросе пропустил кому.