|
PHP |
| Главная PHP | Документация учебники | PHP справочники | | |
Безопасный и удобный поиск.Главное, с чем сталкиваешься при
написании скрипта для поиска - то, что все
кажется простым, но объем кода быстро
нарастает. Обработка строки Первым делом надо порезать ручками строку. $ 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 не
оправдывает затраченного времени. Поэтому
форму для поиска рисуем так: А в поисковом скрипте лишний раз проверяем, что пользователь ввел: if ($
logic!="AND" && $
logic!="OR") Как будет использоваться логика — ниже. Релевантность Наверное, в том же Яндексе
[2] [1] все видели ссылочку "сортировать по
релевантности". Это оно и есть.
Сортировка результатов по количеству
совпадений слов. Статистика поиска Неплохо будет сразу информировать пользователя, сколько он нашел строк таблицы. Для этого делается дополнительный запрос в базу: $ 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). $ request .= "LIMIT $ rows_in_page"; else $ request .= "LIMIT ". $ page*$ rows_in_page. ",". $ rows_in_page; (синтаксис: LIMIT <кол-во строк> либо LIMIT <кол-во
строк отступа>, <кол-во строк>) 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 тысяч раз лазил в базу) в)
увидеть сообщение об ошибке в результате
попадания в строку спецсимволов языка
запросов. Во-вторых, некоторое удобство для
пользователя - постраничный вывод и
подсветка. |