RTFM! статьи, советы, скрипты
::Заработок с помощью сайта ::JScript по-русски! ::Все русские мануалы::
МЕНЮ
О САЙТЕ
НОВОСТИ
СТАТЬИ
КНИГИ
АППЛЕТЫ
СВЯЗЬ

СЧЕТЧИКИ
Rambler's Top100
Рейтинг@Mail.ru
Яндекс цитирования

Безопасный и удобный поиск на PHP

Автор: Gothyc Сайт: http://pauk2001.h1.ru/     Рейтинг: N/A из 7       <<НАЗАД
   
   Главное, с чем сталкиваешься при написании скрипта для поиска - то, что все кажется простым, но объем кода быстро нарастает.
   
   Обработка строки
   Первым делом надо порезать ручками строку.
   $search = substr($search, 0, 64);
   64 символов пользователю будет достаточно для поиска. Теперь каленым железом выжжем все "ненормальные" символы.
   $search = preg_replace("/[^(w)"(x7F-xFF)"(s)]/", " ", $search);
   По идее, нельзя давать пользователю возможности искать по слишком коротким словам - кроме всего прочего, это сильно загружает сервер. Итак, разрешим искать только по словам, которые длиннее двух букв (если ограничение больше, надо заменить "{1,2}" на "{1, кол-во символов}").
   $good = trim(preg_replace("/s([^s]{1,2})s/", " ", ereg_replace("[ ]+", " ","
   $search ")));
   А после замены плохих слов - надо сжать двойные пробелы (они были сделаны специально для корректного поиска коротких слов).
   $good = ereg_eplace("[ ]+", " ", $good);
   
   Логика
   Допустим, мы хотим предоставить пользователю возможность выбирать логику поиска - искать все слова или только одно из нескольких. Если вы хотите сделать как в Яндексе [2] [1] - два амперсанта означают "И" (слово1&&слово2&&слово3) или как-то еще, то я не советчик. Шаманство со строками на небольшом сайте imho не оправдывает затраченного времени. Поэтому форму для поиска рисуем так:
   
   <form name="some"><input type=text name="stroka"><select name="logic">
   <option value="OR">искать любое из слов</option><option value="AND">
   искать все слова</option></select></form>
   
   
   А в поисковом скрипте лишний раз проверяем, что пользователь ввел:
   if ($logic!="AND" && $logic!="OR")
    $logic = "OR";
   Как будет использоваться логика - ниже.
   
   Релевантность
   Наверное, в том же Яндексе [2] [1] все видели ссылочку "сортировать по релевантности". Это оно и есть. Сортировка результатов по количеству совпадений слов.
   
   Отчасти, кстати, такая сортировка снимает проблему обработки логики поиска. Но с БД MySQL делать такую сортировку очень сложно. Надо сперва выбрать, где есть все слова, потом записи, где разные слова (исключив предыдущие). Если у вас постраничный вывод - то вообще дело труба!
   
   Статистика поиска
   Неплохо будет сразу информировать пользователя, сколько он нашел строк таблицы. Для этого делается дополнительный запрос в базу:
   $query = "SELECT id FROM table WHERE field LIKE `%". str_replace(" ", "%` OR
   field LIKE `%", $good). "%`";
   Для статистики по отдельным словам можно сделать следующее:
   $word = explode(" ", $search);
   while (list($k, $v) = each($word)) {
    if (strlen($v)>2)
    $stat[]="$v:". mysql_num_rows(mysql_query("SELECT id FROM table WHERE field
   LIKE `%$v%`"));
    else
    $stat[]="$v: <font color=#cc0000>короткое</font>";
    };
   $word_stats = "Статистика слов: ". implode("", $stat). "<br>";
   unset($stat);
   
   Постраничный вывод результатов
   Ну, когда у нас есть макет для поиска и количество строк результата поиска, сделать постраничный поиск - пара пустяков. Проверяем переменную $page (не меньше 0, не больше $results_amount/$rows_in_page).
   В запрос, который подсчитывает количество строк (смотри выше), пишем нужные нам поля и поля для сортировки. А потом дописываем
   if ($page==0)
    $request .= "LIMIT $rows_in_page";
   else
    $request .= "LIMIT ". $page*$rows_in_page. ",". $rows_in_page;
   (синтаксис: LIMIT <кол-во строк> либо LIMIT <кол-во строк отступа>, <кол-во строк>)
   
   В результате выполнения подобного запроса мы получим именно те самые строки, которые надо выводить на странице.
   
   Для навигации можно либо рисовать ссылки на следующую и предыдущую страницы, либо, что сложнее, делать панель навигации на несколько страниц.
   if ($page>0)
    print ("<a href=search.php?search=". rawurlencode($good). "&page=". ($page-1).
   ">предыдущая страница</a>");
   
   if ($page<$results_amount/$rows_in_page)
    print ("<a href=search.php?search=". rawurlencode($good). "&page=". ($page+1).
   ">следующая страница</a>");
   
   Подсветка
   Чтобы подсвечивать светом или жирным шрифтом искомые слова в тексте, надо сделать всего лишь следующее:
   
   $highlight = "(". str_replace(" ", """, $good). ")";
   Пробелы (а они у нас между словами стоят поодиночке, и нигде двойной пробел не встречается, к тому же с концов строки мы их тоже вырезали) достаточно заменить на вертикальную черту - разделитель вариантов в регулярных выражениях. "Плохие" слова мы не подсвечиваем, потому что в базе их не ищем :).
   
   В коде, который выводит текст пишем:
   
   $row["text"] = ereg_replace($highlight, "<font color=#cc0000>1</font>",
   $row["text"]);
   После написания выпуска я кинулся, было, писать и себе "подсветку". Не тут-то было! У меня в тексте встречаются теги HTML, поэтому пришлось много подумать...
   Получилась вот такая вещь (строка со словами для подсветки есть):
   $text = eregi_replace(">([^<]*)$words", ">1<font color=#cc0000>2</font>3<",
   $text);
   Приходится смотреть, нет в теге ли это слово. Однако тут встает проблема ресурсоемкости такой замены (мой K6-266 над текстом в 5 килобайт думал целых семь секунд). Печально.
   
   
   Итог
   Применяя такие приемы, можно, во-первых, ограничить свободу действий пользователя и не дать ему а) узнать программную структуру сайта б) вызвать перегрузку сервера (например, отправив мегабайт текста, состоящего из слов длиной в три буквы (фраза получилась двусмысленная, но переписывать не буду :), чтобы скрипт 250 тысяч раз лазил в базу) в) увидеть сообщение об ошибке в результате попадания в строку спецсимволов языка запросов. Во-вторых, некоторое удобство для пользователя - постраничный вывод и подсветка.
   


<<НАЗАД      ОЦЕНИТЬ СТАТЬЮ    ВЕРСИЯ ДЛЯ ПЕЧАТИ>>
Статья прочитана :  раз.




пейкюлю



 
 
 
 
 
pauk ©® 2000-2015. All rights reserved.
При перепечатке ссылка на сайт и указание обязательны.
Мнение администрации сайта не всегда совпадает с мнением автора.
Орфография и пунктуация - авторские.
Администрация не несет никакой ответственности за использование материалов.
.
Protected by Copyscape DMCA Takedown Notice Infringement Search Tool