Делаем поиск с подсветкой результатов

Теги:

Раскопал среди старых наработок скрипт поиска, по которому еще год назад собирался написать статью, да все как-то руки не доходили. В общем-то ничего инновационного нет, просто упрощение задачи тем, кому надо написать поиск. Допустим, что искать мы будем в базе данных mysql.

Начнем с таблицы. Опредляем таблицу и поля, по которым производится поиск:

<?php
$namebox='name'; # Поле заголовка записи 
$textbox='text'; # Поле содержимого записи
?>

Форма расширенного поиска у нас будет выглядеть примерно вот так:

<div>
  <form method="get">
         <fieldset><legend>Поиск</legend>
             <p><input type="text" name="search" value="" style='width:350px;'>    <input type="submit" value="Go"></p>
             <p><input type="radio" name="andor" value="0" checked="yes">Любое слово <input type="radio" name="andor" value="1">Все слова
             &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
             Записей на страницу: <select name="artonpage">
                 <option value="5">5</option>
                 <option value="10" selected="yes">10</option>
                 <option value="20">20</option>
                 <option value="40">40</option>
                 <option value="80">80</option>
                 <option value="160">160</option>
             </select></p>
         </fieldset>
     </form>
 </div>

Теперь обрабатываем полученный от пользователя запрос:

<?php //Чтобы работало при отключенном MBSTRING. С русской локалью вечно проблемы.
 function r_strtolower(&$str,$uper=0){
     $up=array('А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я');
     $low=array('а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п','р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я');
     if($uper==1) return str_replace($low,$up,$str);
     else return str_replace($up,$low,$str);
 }
 // Первым делом надо порезать ручками строку.
 // 64 символов пользователю будет достаточно для поиска. Теперь каленым железом выжжем все "ненормальные" символы.
 $search = preg_replace("/[^\\w\\x7F-\\xFF\\s]/", ' ', substr($search, 0, 64));
 // По идее, нельзя давать пользователю возможности искать по слишком коротким словам - кроме всего прочего, это сильно загружает сервер. Итак, разрешим искать только по словам, которые длиннее двух букв (если ограничение больше, надо заменить "{1,2}" на "{1, кол-во символов}").
 $good = trim(preg_replace("/\\s(\\S{1,2})\\s/", ' ', ereg_replace(' +', '  '," $search ")));
 // А после замены плохих слов - надо сжать двойные пробелы (они были сделаны специально для корректного поиска коротких слов).
 $good = ereg_replace(" +", " ", $good); ?> 

После того, как мы прочистили строку поиска, можно заняться формированием поискового запроса:

<?php $search=@$_GET['search']?@$_GET['search']:'';
 $andOr=@$_GET['andor']==1?'AND':'OR';//Встречаются все слова(AND), или хотя бы одно(OR)
 $artOnPage=intval(@$_GET['artonpage'])?intval(@$_GET['artonpage']):10;//Количество выводимых записей на одну страницу  if($good){
     $words=explode(' ',r_strtolower($good));
     function bolder($str){
         return '<b>'.$str.'</b>';
     }
     $bwords=array_map('bolder',$words);
     foreach($words as $word){
         $chars=str_split($word);
         $str='(?:';
         foreach($chars as $char)$str.='(?:'.$char.'|'.r_strtolower($char,1).')';
         $str.=')';
         $arwords[]=$str;
     }
     $rwords=implode('|',$arwords);//['word']==>'((?:w|W)(?:o|O)(?:r|R)(?:d|D))'
       function like_add($txt,$field,$and=0) {
     global $andOr;
     $or=$and?'AND':$andOr;//Если третьим параметром в функции передать 1, то будет вставлено AND вне зависимости от настроек.
     $par="`".$field."` LIKE '%".str_replace(" ","%' $andOr `".$field."` LIKE '%", $txt)."%'";
     return $par;
     }
       $skip=intval(@$_GET['skip'])?intval(@$_GET['skip']):0;
     $pos=$skip*$artOnPage;//Текущий отступ(для sql-запроса)
     $num=mysql_num_rows(mysql_query(" SELECT `id` FROM `page` WHERE ".like_add($good,'name')." OR ".like_add($good,'texter')));
     if($pos>$num){mysql_close($db);die("Ненене! Такой страницы быть не должно!");}
     $pages=$num/$artOnPage;
     //print $rwords;
     $sql_sch=mysql_query(" SELECT *,MATCH `".$namebox."` AGAINST ('".$good."') + MATCH `".$textbox."` AGAINST ('".$good."') AS `relev` FROM `page` WHERE ".like_add($good,'".$namebox."')." OR ".like_add($good,'".$textbox."')."  ORDER BY `relev` DESC limit $pos,$artOnPage");
 } ?> 

Теперь выводим полученные результаты, в процессе подсвечивая их:

<?php if(@$sql_sch){ echo '<h3>Результат поиска: <b>'.$good.'</b><dl></h3>';     while($row=mysql_fetch_assoc($sql_sch)){//print '<h2>Relev: '.$row['relev'].'</h2>';//Если захочется посмотреть релевантность
         $reg='/(.{0,150})('.$rwords.')(.*)$/isU';//print $reg;
         if(preg_match($reg,strip_tags(nl2br($row[$textbox])),$text)){
             $content='...'.preg_replace('/('.$rwords.')/isU','<b>$1</b>',substr($text[0],0,320)).'...';
         }
         else $content=substr(strip_tags(nl2br($row['texter'])),0,320).'...';
         print '<div class=sch_name>'.preg_replace('/('.$rwords.')/isU','<b>$1</b>',$row['namebox]).'</div><div class=sch_texter>'.$content.'</div>';
     }
      ?>
     </dl></div>
     <?php
 } ?>

Добавляем к этому разбиение результатов на страницы:

<?php     if ( @$pages > 1 ){?>
         <div id="paging">[ <?php
             $pages_link = array();
             for ( $i = 0; $i < $pages; $i++ )$pages_link[] = '<a href="?search='.@$_GET['search'].'&artonpage='.@$_GET['artonpage'].'&andor='.@$_GET['andor'].'&skip='.$i.'">'.( $skip == $i?'<b>'.$i. '</b>':$i).'</a>';
             echo implode ( " ", $pages_link );
           ?> ]</div><?php
     }
 ?>

Спонсоры статьи

Статьи схожей тематики:

PHP-функция для получения полного URL текущей страницы

Neutrino Atomic Edition 0.8.7

Улучшенная система PHP-хуков

Хуки в PHP

Предлагаю вашему вниманию...

Комментарии(3):

rss-лента

Добавлено: 2010-09-09 01:19:16, Михаил

У меня сразу не заработалл, в коде есть ошибки. Неплохо дать ссылку файл скрипта. А вообще статья 5+.

Добавлено: 2011-08-05 00:30:29, ошибки

Бесплатный чат общение онлайн развлечения и игры tolxy chat tolxy.vx8.ru

Добавлено: 2011-11-23 12:49:53, Дмитрий

У меня тоже не заработало, а вот как убрать не которые ошибки я не знаю, можете подсказать какая в этой строке ошибка "$chars=str_split($word);", а то вот такое выдает "Fatal error: Call to undefined function: str_split()"

Добавить комментарий

Ваше имя:*
Ваш email:*(не публикуется)
Ваш блог:
Ваш комментарий:*

Переносы строк и url-адреса преобразуются автоматически, не забудьте отделить их пробелами. html и bb-коды не поддерживаются.