Подходящий поиск на php
Как можно сделать более хороший подходящий поиск по сайту с помощью php в связке с mysql.
Часто встречаются сайты, на которых поиск идет по средствам деления фразы на слова и выводились результаты не те, которые нужны пользователю. Предлагаем рассмотреть наш скрипт, который будет выдавать результаты в более подходящем порядке.
Структура базы
В БД создаем несколько таблиц:
1. Страница контента
CREATE TABLE `content` (
`page_id` INT NOT NULL AUTO_INCREMENT ,
`page_name` TEXT NOT NULL ,
`page_curl` TEXT NOT NULL ,
`page_text` TEXT NOT NULL ,
`page_views` INT NOT NULL ,
PRIMARY KEY ( `page_id` ) ,
UNIQUE (
`page_id`
)
) ENGINE = MYISAM ;
2. Страница запросов
CREATE TABLE `search_words` (
`word_id` INT NOT NULL AUTO_INCREMENT ,
`word_words` TEXT NOT NULL ,
`word_count` INT NOT NULL ,
PRIMARY KEY ( `word_id` ) ,
UNIQUE (
`word_id`
)
) ENGINE = MYISAM ;
После создания таблиц в БД пишем php код
1. Принять и почистить данные
Все данные передаем методом POST для того, чтобы никто не менял адресную строку. Фраза, которую ищет пользователь будет храниться в переменно: $_POST[«words»].
Для начала нам нужно поставить защиту от нежелательных атак.
function clean_post_data($data){
$data = strip_tags($data);
$data = strtolower($data);
$data = preg_replace('~[^a-z0-9 \x80-\xFF]~i', "",$data);
return $data;
}
Данная функция очистит все ненужное из текста.
Вторым шагом мы создадим функцию которая позволит создать массив с нужными для поиска словами:
function clean_array_to_search($words = array(), $max = 0, $min_length){
$result = array();
$i = 0;
foreach($words as $key => $value){
if(strlen(trim($value)) >= $min_length){
$i++;
if($i <= $max){
$result[] = trim($value);
}
}
}
return $result;
}
Третьим шагом мы составим функцию, которая будет выбирать из базы данных страницы, которые подходят под поисковую фразу.
function get_results($words){
$sql = "SELECT * FROM (`content`) WHERE ";
$i = 0;
foreach($words as $key => $value){
$i++;
$sql = $sql." `page_name` LIKE '%".$value."%' OR `page_text` LIKE '%".$value."%'".($i==count($words)?"":" OR");
}
$sql .= " ORDER BY `page_views` DESC";
$result = mysql_query($sql);
while($row = @mysql_fetch_object($result)){
$return = $row;
}
return $return;
}
После того, как мы получили массив с данными нам нужно отсортировать его с помощью функции.
function get_matches($content, $word = array()){
$matches = array();
foreach($content as $p){
$res[$p->page_id] = $p;
foreach($word as $w){
if(trim($w) != ""){
$w = trim($w);
$matches[$p->page_id] = $matches[$p->page_id] + count(explode($w, $p->page_name));
$matches[$p->page_id] = $matches[$p->page_id] + count(explode($w, $p->page_text));
}
}
}
arsort($matches);
$i = 0;
foreach($matches as $k => $v){
$result[$i] = $res[$k];
$result[$i]->matches = $v;
$i++;
}
return $result;
}
В результате, чтобы сделать поиск нам нужно сделать следующее.
$max = 10; // максимальное количество слов во фразе
$min_length = 3; // минимальная длина искомого слова
$word = explode(" ", clean_post_data($_POST["word"]));
$words = clean_array_to_search($word, $max, $min_length);
$results = get_results($words);
$result = get_matches($results, $words);
Мы получили список того, что пользователь искал, причем в нужном ему порядке. В самом начале была информация, что данные передаются методом POST поэтому нужно выполнить еще пару команд, чтобы можно было видеть результаты поиска:
function insert_into_search_table($words = array()){
$words = implode(" ", $words);
$sql = "INSERT INTO `search_words` (`word_id`, `word_words`) VALUES (NULL, '".$words."');";
mysql_query($sql);
return intval(mysql_insert_id());
}
В самый верх страницы мы вставим следующую строку, для того, чтобы любой, пройдя по ссылке мог получить те результаты которые получил ранее.
if(isset($_GET["words_id"]) AND $_GET["words_id"] != "" AND $_GET["words_id"] == intval($_GET["words_id"])){
$row = mysql_query("SELECT * FROM `search_words` WHERE `word_id` = '".intval($_GET["words_id"])."';");
$row = @mysql_fetch_array($row);
$_POST["word"] = $row["word_words"];
}
В итоге вы получаете массив с объектами: $result.