Поиск по таблице MySql базы на PHP

При разработке интернет магазина компьютерной техники для сайта eAiTi.ru я столкнулся с необходимостью сделать сложный поиск, который бы искал любые вхождения на любых местах в поисковом запросе.

Ниже я привожу несколько укороченный код, который сохраняет все необходимые элементы для функционирования.

Особенности кода:

  • Контекстный поиск отдельных слов, введенных через пробел в строке запроса
  • Подсветка найденных фрагментов
  • Сортировка по цене или по наименованию
  • Постраничный вывод, номера страниц выводятся сверху и снизу
// подключение к базе MySql
require_once($_SERVER['DOCUMENT_ROOT'].'/config.php');
// если передан поисковый запрос
if($q){
   $ar_q=explode(" ", $q);
   $add_sql='';
   for($i=0;$i<count($ar_q);$i++)
    $add_sql.=' ((locate("'.strtolower(addslashes($ar_q[$i])).'",lower(price.name))>0) or'.
          ' ("'.strtolower(addslashes($ar_q[$i])).'"=lower(price.kod_prodact))) and';
   $add_sql=' WHERE'.$add_sql.' ost<>"нет"';
   $add_q=($q?'&q='.urlencode($q):'');
}else{
    $add_sql=' WHERE ost<>"нет"';
    $add_q='';
}

// Общее количество информации
//$count = mysql_numrows(sql('SELECT * from price '.$add_sql));
$row = mysql_fetch_assoc(sql('SELECT count(*) as counter from price '.$add_sql));
$perpage = 20; // Количество отображаемых данных из БД на одной странице
$count=intval($row['counter']); // общее кол-во товаров

if($count){

$pages_count = ceil($count / $perpage); // Количество страниц
// Если номер страницы оказался больше количества страниц
if ($page > $pages_count) $page = $pages_count;
$start_pos = ($page - 1) * $perpage; // Начальная позиция, для запроса к БД

$bar=link_bar($page, $count, $pages_count, 8);
echo $bar;

// сортировка по наименованию или цене
$ord = @$_GET['ord']; if(($ord<>'name')&&($ord<>'price'))$ord='name';
if($ord=='price'){
    print "<h3><a href=\"".$_SERVER['PHP_SELF'].'?page='.$page.$add_q."\">Наименование</a></h3>
    ↓Цена<a href='#price'><sup>*</sup></a> \n";
    $add_q.='&ord=price';
}else
    print "<h3>↓Наименование</h3>
    <a href=\"".$_SERVER['PHP_SELF'].'?page='.$page.$add_q."&ord=price\">Цена</a> \n";

// Вывод информации из базы данных
$result = sql('SELECT * from price '.$add_sql.' ORDER BY '.$ord.' LIMIT '.$start_pos.', '.$perpage);
while ($row = mysql_fetch_assoc($result)) {
   $name=($q?preg_replace("/(".str_replace('/','\/',$q).")/si",'<font color=red>\\1</font>',htmlspecialchars($row['name'])):htmlspecialchars($row['name']));// Подсветка

   print "<h3 id='n".$row['id']."'>".$name."</h3>
    ".number_format($row['price'], 0, '.', ' ')." руб.";    // цена
   }
echo " <br clear=all />$bar<span class='it'>".($q?"Найдено по запросу":"Всего")." <b>".number_format($count, 0, '.', ' ')."</b> товаров.</span>";
}else print "<h3>По вашему запросу ничего не найдено!</h3>";

Функция вывода постраничной навигации:

function link_bar($page, $count, $pages_count, $show_link)
{global $add_q;
// $show_link - это количество отображаемых ссылок;
// нагляднее будет, когда это число будет парное
// Если страница всего одна, то вообще ничего не выводим
if ($pages_count == 1) return '';
$out='';
$begin = $page - intval($show_link / 2);

// Сам постраничный вывод
// Если количество отображ. ссылок больше кол. страниц
if ($pages_count <= $show_link + 1) $show_dots = 'no';
// Вывод ссылки на первую страницу
if (($begin > 2) && ($pages_count - $show_link > 2))
    $out.='<a href="'.$_SERVER['PHP_SELF'].'?page=1'.$add_q.'" title="в начало"> << </a> ';

for ($j = 0; $j <= $show_link; $j++) // Основный цикл вывода ссылок
{  $i = $begin + $j; // Номер ссылки
   // Если страница рядом с началом, то увеличить цикл для того,
   // чтобы количество ссылок было постоянным
   if ($i < 1) continue;
   // Подобное находится в верхнем цикле
   if (!isset($show_dots) && $begin > 1) {
   $out.=' <a href="'.$_SERVER['PHP_SELF'].'?page='.($i-1).$add_q.'"><b>...</b></a> ';
   $show_dots = "no";
   }
   // Номер ссылки перевалил за возможное количество страниц
   if ($i > $pages_count) break;
   if ($i == $page) $out.=' <a><b>'.$i.'</b></a> ';
   else $out.=' <a href="'.$_SERVER['PHP_SELF'].'?page='.$i.$add_q.'">'.$i.'</a> ';

   // Если номер ссылки не равен кол. страниц и это не последняя ссылка
   if (($i != $pages_count) && ($j != $show_link)) $out.=' ';// Разделитель ссылок
   // Вывод "..." в конце
   if (($j == $show_link) && ($i < $pages_count))
    $out.=' <a href="'.$_SERVER['PHP_SELF'].'?page='.($i+1).$add_q.'"><b>...</b></a> ';

}
// Вывод ссылки на последнюю страницу
if ($begin + $show_link + 1 < $pages_count)
    $out.=' <a href="'.$_SERVER['PHP_SELF'].'?page='.$pages_count.$add_q.'" title="в конец"> >> </a>';

return "\n".$out."\n";
} // Конец функции

.