Делаем поиск с подсветкой результатов
Раскопал среди старых наработок скрипт поиска, по которому еще год назад собирался написать статью, да все как-то руки не доходили. В общем-то ничего инновационного нет, просто упрощение задачи тем, кому надо написать поиск. Допустим, что искать мы будем в базе данных 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">Все слова
Записей на страницу: <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
}
?>Спонсоры статьи
- Статьи схожей тематики:

Комментарии(3):
rss-лентаДобавлено: 2010-09-09 01:19:16, Михаил
Добавлено: 2011-08-05 00:30:29, ошибки
Добавлено: 2011-11-23 12:49:53, Дмитрий