Скрипт PHP для поиска на сайте
Здравствуйте, друзья. Хочу с вами поделиться скриптом, который вы можете использовать по своему усмотрению. Я уверен, что вы сможете легко его усовершенствовать под свои нужды. В конце статьи вы найдете ссылку на скачивание этого скрипта. В исходниках скрипта вы найдёте необходимые файлы для его встраивания на свой сайт. Также в конце статьи вас ждет ссылка на один неплохой материал, который, я надеюсь, поможет вам усовершенствоваться как разработчику. А теперь к делу! Для начала создадим таблицу, в которой будут хранится найденные статьи:
CREATE TABLE `searchers` ( `id` int(5) NOT NULL, `title` varchar(255) NOT NULL DEFAULT "", `text` text NOT NULL, `description` text NOT NULL, `mini_img` varchar(255) NOT NULL DEFAULT "", `relevation` int(5) NOT NULL, KEY `id` (`id`), ) ENGINE=MyISAM AUTO_INCREMENT=104 DEFAULT CHARSET=cp1251;
Для работы с таблицой «searchers» будем использовать класс «Search» из файла «Search.class.php»:
<?php require_once "DB.class.php"; class Search { public $id; public $title; public $text; public $description; public $mini_img; public $relevation; //Конструктор создаёт новый поисковый объект function __construct($data) { $this->id = (isset($data["id"])) ? $data["id"] : ""; $this->title = (isset($data["title"])) ? $data["title"] : ""; $this->text = (isset($data["text"])) ? $data["text"] : ""; $this->description = (isset($data["description"])) ? $data["description"] : ""; $this->mini_img = (isset($data["mini_img"])) ? $data["mini_img"] : ""; $this->relevation = ( isset($data["relevation"])) ? $data["relevation"] : ""; } public function save($isNewArticle = FALSE) { //Создаём новый объект БД $db = new DB(); // Заменям все апострофы в тексте на двойные кавычки, // чтобы данные записались в БД без ошибок. $text = str_replace(""", """, $this->text); // Если статья присутствует в БД, то обновляем if(!$isNewArticle) { $data = array( "title" => ""$this->title"", "text" => """.$text.""", "description" => ""$this->description"", "mini_img" => ""$this->mini_img"", "relevation" => ""$this->relevation"" ); //обновим строку в БД $db->update($data, "searchers", "id = ".$this->id ); }else{ // Если статьи ещё нет в БД, то добавляем $data = array( "id" => ""$this->id"", "title" => ""$this->title"", "text" => """.$text.""", "description" => ""$this->description"", "mini_img" => ""$this->mini_img"", "relevation" => ""$this->relevation"" ); //добавим строку в БД $this->id = $db->insert($data, "searchers"); } return true; } } ?>
Как видите мы подключаем еще один класс «DB» из файла «DB.class.php» для работы с базой:
<?php class DB { // Свойства класса protected $db_name = "mydbname"; // Имя Вашей базы protected $db_user = "mydbuser"; // Имя пользователя Вашей базы protected $db_pass = "mypassword"; // Пароль к Вашей базе protected $db_host = "myhostname"; // Имя хоста, может быть "localhost" // Методы класса public function GetHost() { return $_SERVER["HTTP_HOST"]; } public function connect() { $db=mysql_connect($this->db_host,$this->db_user,$this->db_pass); mysql_select_db($this->db_name,$db); return $db; } //Обновляет таблицу БД public function update($data, $table, $where) { foreach ($data as $column => $value) { $sql = "UPDATE $table SET $column = $value WHERE $where"; mysql_query($sql) or die(mysql_error()); } return true; } //Удаляет строки из таблицы БД public function delete($table, $where) { $sql = "DELETE FROM $table WHERE $where"; mysql_query($sql) or die(mysql_error()); return true; } //Вставляет новую строку в таблицу БД public function insert($data, $table) { $columns = ""; $values = ""; foreach ($data as $column => $value) { $columns .= ($columns == "") ? "" : ", "; $columns .= $column; $values .= ($values == "") ? "" : ", "; $values .= $value; } $sql = "insert into $table ($columns) values ($values)"; mysql_query($sql) or die(mysql_error()); //Выводит ID return mysql_insert_id(); } } ?>
Измените свойства класса «DB», добавив информацию о Вашей базе.
Теперь напишем основные строки кода из файла «view_search.php»:
<?php // Подключаем поисковый класс require_once "classes/Search.class.php"; // Объявляем переменные $endings = "ых|ый|ы|ой|ое|ые|ому|ом|ами|ам|ая|ат|ать|а| овый|ов|ого|ох|о|у|ему|ей|е|ство|ия|ий|и|ять|ь|я|он|ют|"; //Ставим окончания с большим количеством символов вперед, //например, если первая "е", то "|ему|ей|е|". $endings_arr = explode("|",$endings); // Получаем массив из слов в нижнем регистре $search_arr = explode(" ",strtolower($search)); // Получаем массив слов со всеми имеющимися у нас окончаниями $SearchArray = GetSearchArrayX($search); //Удалим все строки из таблицы $db1 = new DB(); $db = $db1->connect(); $db1->delete("searchers", "id<>0"); if ($SearchArray <> "") { echo "<p class=".p_class."> Результаты для <strong><em>".$search."</em></strong> </p>"; // Укажите здесь название таблицы, в которой нужно искать $tbl ="NameOfYourTable"; // Найдём слова в заголовке статьи SearchWords($SearchArray, "title", $db, $tbl); // Найдём слова в тексте статьи SearchWords($SearchArray, "text", $db, $tbl); // Выведем статьи из таблицы поиска ViewArticles($SearchArray, $db); }else{ echo "<p class=".p_class.">Информация по Вашему запросу не найдена.</p>";} ?>
Теперь по порядку покажем описание функций, используемых здесь. Описание функции «GetSearchArrayX»:
<?php // функция добавления слов с окончаниями в массив function GetSearchArrayX($query) { global $endings_arr; // Заносим слова, разделенные пробелом в массив $words = explode(" ",$query); //создаем пустой массив $SearchArray = array(); //создаем пустую строку $SearchArray_str = ""; foreach ($words as $word) { $j=0; $word = trim($word); //пропускаем, если слово короче трёх символов if (strlen($word)<3) { unset($word); } else { if (strlen($word)>2) { $WithoutEnding = DeleteEndings($word); // первым ставим слово без окончания if ($j == 0) { if ($word != $WithoutEnding) { $SearchArray_str=$SearchArray_str." ".$WithoutEnding; } $SearchArray_str=$SearchArray_str." ".$word; } $j++; foreach ($endings_arr as $ending){ // Если находим слово с таким же окончанием продолжаем if ($word == $WithoutEnding.$ending) { continue; } $SearchArray_str=$SearchArray_str." " .$WithoutEnding.$ending; } } else { $SearchArray_str=$SearchArray_str." ".$word; } } } $SearchArray = explode(" ",trim($SearchArray_str)); return $SearchArray; //возвращаем полученный массив } // GetSearchArrayX ?>
Описание функции «DeleteEndings»:
<?php // Функция удаления окончаний function DeleteEndings($word) { global $endings; $reg = "/(".$endings.")$/i"; $word = preg_replace($reg,"",$word); //удаляем окончания return $word; } ?>
Описание функции «SearchWords»:
<?php function SearchWords($SearchArray, $column, $db, $tbl = "data") { global $search; $query_str = "SELECT id,text,mini_img,title,description FROM ".$tbl." WHERE "; $SearchArray_ = GetSearchArray($search); foreach ($SearchArray_ as $word) { // ищем вхождение слова $result1 = mysql_query($query_str."(".$column." LIKE "%$word%")",$db); if (!$result1) { echo "<p align="center"> Запрос на выборку данных из базы не прошел. Напишите об этом администратору сайта. <br> <strong>Код ошибки:</strong></p>"; exit(mysql_error()); } if (mysql_num_rows($result1) > 0) { while($row = mysql_fetch_assoc($result1)) { if (isset($row)) { // проверим есть ли запись с таким id $check_id = check_id($row[id], $db); if($check_id) { // если да, пропускаем continue; } //создать новый объект поиска $newSearch = new Search($row); //сохранить новый поиск в БД $newSearch->Save(TRUE); } } } } } // SearchWords() ?>
Описание функции «check_id»:
<?php // Проверяем есть ли запись в таблицы с таким id function check_id($id, $db) { $result = mysql_query (" SELECT id FROM searchers WHERE (id=".$id.")", $db); if (!$result) { echo "<p align="center">Запрос на выборку данных из базы не прошел. Напишите об этом администратору сайта. <br> <strong>Код ошибки:</strong></p>"; exit(mysql_error()); } if (mysql_num_rows($result) > 0) { return TRUE; } else { return FALSE; } } // check_id ?>
Описание функции «ViewArticles»:
<?php // Функция вывода найденных статей из таблицы поиска function ViewArticles($SearchArray, $db){ SearchArticles($SearchArray); $arts = mysql_query (" SELECT * FROM searchers WHERE relevation <> 0 ORDER BY relevation DESC", $db); if (!$arts) { echo "<p align="center">Запрос на выборку данных из базы не прошел. Напишите об этом администратору сайта. <br> <strong>Код ошибки:</strong></p>"; exit(mysql_error()); } if (mysql_num_rows($arts) > 0) { while($articles = mysql_fetch_assoc($arts)) { $text = $articles["description"]; $id = $articles["id"]; print <<<HERE <br> <table align="center" class="post"> <tr> <td class="post_title"> <p class="post_name"><img class="mini" align="left" src="https://site.softmaker.kz/files/a></p> </td> </tr> <tr> <td>$text <p class="post_view"><span style="background-color: #ffec82;"> Число вхождений: $articles[relevation]</span></p> </td> </tr> </table> HERE; } } else { print <<<HERE <p class="post_title2">Информация по Вашему запросу не найдена.</p> HERE; } } // ViewArticles ?>
Описание функции «SearchArticles»:
<?php // Функция для добавления выделенных слов в таблицу searchers function SearchArticles($SearchArray) { global $db, $search; // Эта переменная нужна, чтобы узнать были ли совпадения $was = 0; // Выбираем все статьи из таблицы поиска $arts = mysql_query ( "SELECT * FROM searchers ORDER BY relevation DESC", $db); if (!$arts) { echo "<p align="center"> Запрос на выборку данных из базы не прошел. Напишите об этом администратору сайта. <br> <strong>Код ошибки:</strong></p>"; exit(mysql_error()); } if (mysql_num_rows($arts) > 0) { while($article = mysql_fetch_assoc($arts)){ $title = $article[title]; // можно так: // $title = htmlspecialchars(strip_tags($material[title])); $text = $article[text]; // можно так: // $text = htmlspecialchars(strip_tags($material[text])); $description = $article[description]; $CountOfEntry =0; //число вхождений слова $relevation = 0; $SearchArray_ = GetSearchArray($search); // Цикл по массиву слов без окончаний foreach ($SearchArray_ as $word) { $word_l = strtolower($word); $WithoutEnding = DeleteEndings($word_l); //Создадим маску для поиска с помощью регулярной функции $reg = "/(".$word_l.")/"; if ($word_l == $WithoutEnding) { // подсчитываем количество вхожений в заголовке, // тексте и описании $CountOfEntry = preg_match_all($reg, strtolower($title), $out); $CountOfEntry += preg_match_all($reg, strtolower($text), $out); $CountOfEntry += preg_match_all($reg, strtolower($description), $out); $article[relevation] += $CountOfEntry; // увеличиваем число вхождений слова // окрашиваем совпадения в заголовке, тексте и описании $title = MarkAll($word_l, $title); $text = MarkAll($word_l, $text); $description = MarkAll($word_l, $description); } } //Добавляем в таблицу только те статьи, //которые имеют хотя бы одно вхождение if($article[relevation]!=0) { $was = 1; $article[title] = $title; $article[text] = $text; $article[description] = $description; //создать новый объект поиска $newSearch = new Search($article); //обновить поиск в БД $newSearch->Save(); } else { unset($article); } } } // Если не было совпадений, выводим сообщение if ($was == 0) { echo "<p align="center"> Информация в статьях по Вашему запросу не найдена. </p>"; } return $article; } ?>
Описание функции «GetSearchArray»:
<?php //функция добавления слов без окончаний в массив function GetSearchArray($query) { global $endings_arr; //Заносим слова, разделенные пробелом в массив $words = explode(" ",$query); //создаем пустой массив $SearchArray = array(); //создаем пустую строку $SearchArray_str = ""; foreach ($words as $word) { $word = trim($word); //пропускаем, если слово короче трёх символов if (strlen($word)<3) { unset($word); } else { if (strlen($word)>2) { $WithoutEnding = DeleteEndings($word); $SearchArray_str=$SearchArray_str." ".$WithoutEnding; } else { $SearchArray_str=$SearchArray_str." ".$word; } } } $SearchArray = explode(" ",trim($SearchArray_str)); return $SearchArray; //возвращаем полученный массив } // GetSearchArray ?>
Описание функции «MarkAll»:
<?php // Функция для выделения найденных слов в тексте function MarkAll($word, $string) { global $endings_arr, $search_arr; // если не находим слова без окончания, значит не найдём ничего if (stristr ($string, $word) == FALSE) { return $string; } // Сначала окрашиваем целые слова с окончаниями foreach ($search_arr as $search){ if (stristr($search, $word) == FALSE) { continue; } $pattern = "/b".$search."b/i"; $replacement = "<mark>".$search."</mark>"; $string = preg_replace($pattern, $replacement, $string); } // Находим слово без окончания и окрашиваем его if (in_array($word, $search_arr)) { $pattern = "/b".$word."b/i"; $replacement = "<mark>".$word."</mark>"; $string = preg_replace($pattern, $replacement, $string); } // Добавляем к слову без окончания все окончания и окрашиваем foreach ($endings_arr as $ending){ $pattern = "/b".$word.$ending."b/i"; $replacement = "<mark>".$word.$ending."</mark>"; $string = preg_replace($pattern, $replacement, $string); } return $string; } // MarkAll ?>
Это что получается данные к базе сможет увидить каждый кто откроет DB.class.php(имя базы,имя пользователя,пароль?
Здравствуйте, Сергей!
Даже, если смогут открыть, что мало вероятно, то увидят текст, который видите вы. А не данные из базы.
Отличный скрипт, спасибо! Есть конечно к чему придраться, но это лучшее что есть в сети-))
Немного доработал, прикрутил постраничную навигацию…
У меня вот только пока ни как не получилось настроить подсветку для русского текста, т.е. латиницу подсвечивает, а кириллицу нет((
Если знаете, подскажите пожалуйста.
И у меня еще вопрос, я так лр конца и не понял принцип работы в целом…. При поиске данные временно заносятся в таблицу, может быть накладка обращения к таблице, если например несколько пользователей будут использовать скрипт?
Спасибо, я думаю, что второй запрос будет ожидать завершение первого.