Поиск по сайту AJAX + PHP + MySQL (PHP + MySQL)


Поиск по сайту  AJAX + PHP + MySQL (PHP + MySQL)

Добрый день дорогие друзья, здравствуйте.
Никак не дает мне покоя вопрос организации пользовательского поиска по сайту. И в этой статье я снова хочу обратиться к нему и рассказать как реализовать поиск используя связку AJAX + PHP + MySQL.

То есть на этот раз я не буду пользоваться услугами сторонних сервисов, а покажу как это можно реализовать самостоятельно, используя лишь только то, чем мы располагаем. А именно: cервер PHP и сервер MySQL с развернутой на нем базой данных в которой хранится иформация о сайте.

А связать все воедино - передачу поискового запроса серверу и выдачу информации по нему в браузер после обработки, поможет технология AJAX.

Реализовывать поиск, по моему замыслу, мы будем с помощью AJAX (клиентская часть) и PHP + MySQL(серверная часть)

Цели определены, давайте теперь разработаем алгоритм наших действий

Сформулируем сначала задачу:


Из поисковой формы с помощью технологии AJAX, основы которой продемонстрированы в статьях "Пример AJAX приложения - Телефонная книга (сервер)" и "Пример Ajax приложения - Телефонная книга (клиент)", строка запроса передается на сервер, где в PHP скрипте происходит его обработка и формируется запрос к базе данных MySQL.

Скрипт PHP получает от сервера MySQL ответ с результатами поиска в базе данных, генерирует HTML с поисковой выдачей и AJAX - ом передает его клиенту(браузеру), после чего он отображается на экране.

В сегодняшней статье я рассмотрю связку PHP + MySQL и покажу как как организовать простой вывод найденной информации в браузер. А уже в статье "Поиск по сайту AJAX + PHP + MySQL (AJAX)" я рассмотрю как "прикрутить" ко всему этому AJAX оптимизировав тем самым вывод поисковой информации пользователю.


И так, приступим


Для наглядности я решил объединить весь код в один файл. Но вы должны учесть, что если интеграция кода HTML и PHP дело в общем обычное, то объединение в один файл конфигурационных настроек подключения к базе данных, вспомогательных функций PHP и непосредственно самого исполняемого скрипта PHP в один файл дело недопустимое, и что конечно правильнее разносить их по отдельным файлам. Так сказать мухи отдельно, котлеты отдельно.

Для начала вот вам код, который у меня получился:


Свернуть код:
<form name="search" method="post" action="search.php">
    <input type="search" name="query" placeholder="Поиск" />
    <button type="submit">Поиск</button> 
</form>


<?php 
header ("Content-type:text/html; charset=utf-8");

/////////////// Определяем используемые функции //////////////////

 /* Открываем соединение с базой данных*/
function connectDB (){
// Определяем константы для соединения с базой данных
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'db_name');

//Пытаемся соединится с базой данных
$dbconn = mysql_connect(DB_HOST, DB_USER, DB_PASS)
  or die("Ошибка соединения с базой данных! " . mysql_error());
//и выбрать таблицу
mysql_select_db(DB_NAME); 
// Устанавливаем кодировку
mysql_query('SET NAMES utf8');
//Возвращаем дескриптор соединения
return $dbconn;
}

/*Закрываем соединение с базой данных*/
function closeDB($dbconn){
mysql_close($dbconn);
}

/*Обработка поискового запроса*/
function search ($query) { 
$text = '';

// Проводим фильтрацию данных
$query = trim($query);                     // Обрезаем пробелы и спецсиволы
$query = strip_tags($query);               // Удаляем HTML и PHP теги
$query = mysql_real_escape_string($query); // Экранируем специальные символы

	
//Поисковый запрос не пустой?
if (!empty($query)){
  if (strlen($query) < 4) {
    $text = '<p>короткий поисковый запрос.</p>';
  }elseif (strlen($query) > 128) {
    $text = '<p>длинный поисковый запрос.</p>';
  } else {
    //Формируем строку поискового запроса 
    $sql = "SELECT `id`, `title`, `description`, `link`
      FROM `name_table` WHERE `description` LIKE '%$query%'
      OR `title` LIKE '%$query%'";
    // и выполняем его
    $result = mysql_query($sql);
    //Определим колличество найденных совпадений
    $num = mysql_num_rows($result);
    //Если число совпадений (строк результата запроса) больше 0 
    if ( $num > 0) { 
      //Получаем ассоциативный массив
      $row = mysql_fetch_assoc($result); 
      //и начинаем формировать строку поисковой выдачи
      $text .= '<p>По вашему запросу  <strong>'.$query.'</strong>';
      $text .= ' найдено '.$num.' совпадений</p>' ;

      do {
        //Продолжаем  формировать строку поисковой выдачи
        $text .= '<p><a href="http://'.$row['articleId'].'">';
        $text .= $row['title'].'</a></p>';
        $text .= '<p>'.$row['tinyDescription'].'</p>';
        // Делаем это пока у нас есть результаты
      } while ($row = mysql_fetch_assoc($result)); 
    } else {
      // Найти совпадение не удалось 
      $text = '<p>По вашему запросу ничего не найдено.</p>';
    }
  } 
}else {
  $text = '<p>Задан пустой поисковый запрос.</p>';
}
//Возвращаем сформированную строку поисковой выдачи
return $text; 
}

///////////// Сам скрипт обработчик ///////////////
if (isset ($_POST['query'])){ 
  // Открываем соединение с базой данных
  $connect = connectDB();
  $search_result = search ($_POST['query']); 
  echo $search_result; 
  // Закрываем соединение с  базой данных
  closeDB ($connect);
}
?>

Ну вот, а теперь, когда вы бегло просмотрели код, давайте разберем как он работает.

Первым делом создадим форму поиска , которая отправляет поисковый запрос серверу:

<form name="search" method="post" action="search.php">
    <input type="search" name="query" placeholder="Поиск" />
    <button type="submit">Поиск</button> 
 </form>

Думаю, что по по HTML форме у вас не должно возникнуть вопросов, но если это все таки случится, то ответы на них можно найти в статьях: "О HTML формах и не только", "HTML, формы и CSS (часть1 - HTML)" и "HTML, формы и CSS (часть2 - CSS)"

А вот на скрипте отвечающем за соединение с базой данных MYSQL и выполнением запроса к базе хочу остановится немного поподробнее

Сначала идет блок кода в котором инициализируются параметры для подключения к базе данных и создается само подключение - функция connectDB(), а также функция closeDB() - которая закрывает соединение с базой данных. Естественно, что данные названий таблиц, выбираемых из таблиц параметров, пароля для подключения к базе данных и имя самой базы данных нужно задать собственные.

<?php 

 /* Открываем соединение с базой данных*/
function connectDB (){
// Определяем константы для соединения с базой данных
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'db_name');

//Пытаемся соединится с базой данных
$dbconn = mysql_connect(DB_HOST, DB_USER, DB_PASS)
  or die("Ошибка соединения с базой данных! " . mysql_error());
//и выбрать таблицу
mysql_select_db(DB_NAME); 
// Устанавливаем кодировку
mysql_query('SET NAMES utf8');
//Возвращаем дескриптор соединения
return $dbconn;
}

/*Закрываем соединение с базой данных*/
function closeDB($dbconn){
mysql_close($dbconn);
}

А дальше мы подошли к основной функции search() в которой происходит вся основная работа, и в которую передается параметр для обработки - строка запроса $query.

/*Обработка поискового запроса*/
function search ($query) { 
$text = '';

Сначала фильтруем строку запроса обрезая пробелы и управляющие символы trim(), экранируя специальные символы mysql_real_escape_string(), чтобы запрос стал безопасным для базы данных. Настоятельно рекомендую проводить такую обработку , так как любая форма на Вашем сайте - это потенциальная уязвимость, образно говоря "черный вход" для злоумышленников. Ведь вы же не собираетесь оставить его открытым?

// Проводим фильтрацию данных
$query = trim($query);                     // Обрезаем пробелы и спецсиволы
$query = strip_tags($query);               // Удаляем HTML и PHP теги
$query = mysql_real_escape_string($query); // Экранируем специальные символы

Далее переходим непосредственно к поисковому запросу Сначала проверим не пустой !empty() ли пришел поисковый запрос?

Если запрос пустой, то возвращаем соответствующее сообщение пользователю. Если проверка пройдена, проверяем его на размер.

Нас не интересуют запросы короче 4 или длиннее 128 символов. Запрос не удовлетворяет нашим требованиям - снова выводим соответствующие сообщения для пользователя. Ну а если все хорошо, выполняем запрос к базе данных.

//Поисковый запрос не пустой?
if (!empty($query)){
  if (strlen($query) < 4) {
    $text = '<p>короткий поисковый запрос.</p>';
  }elseif (strlen($query) > 128) {
    $text = '<p>длинный поисковый запрос.</p>';
  } else {

А вот с этого места поподробнее...
Сначала в строковой переменной $sql формируем строку запроса. C помощью оператора SELECT, который делает выборку идентификатора страницы (id), ее заголовка (title), описания (description) и ссылки на страницу (link), выбираем из таблицы (FROM table_name) значения полей где (WHERE) в любом месте заголовка или описания содержится наш поисковый запрос ( `description` LIKE '%$query%' OR `title` LIKE '%$query%').

//Формируем строку поискового запроса 
    $sql = "SELECT `id`, `title`, `description`, `link`
      FROM `name_table` WHERE `description` LIKE '%$query%'
      OR `title` LIKE '%$query%'";
    // и выполняем его
    $result = mysql_query($sql);
    //Определим колличество найденных совпадений
    $num = mysql_num_rows($result);
    //Если число совпадений (строк результата запроса) больше 0 
    if ( $num > 0) { 
      //Получаем ассоциативный массив
      $row = mysql_fetch_assoc($result); 
      //и начинаем формировать строку поисковой выдачи
      $text .= '<p>По вашему запросу  <strong>'.$query.'</strong>';
      $text .= ' найдено '.$num.' совпадений</p>';

Если найти ничего не удалось - выводим об этом сообщение пользователю. Если запрос возвратил хотя бы одну запись, формируем в цикле (DO WHILE ) особенностью которого является, что он выполняется по крайней мере один раз, строку ответа сервера клиенту с результатами поисковой выдачи. Естественно, что если запрос к базе вернул не одну, а несколько записей, то все они в цикле методом конкатенации "пристыкуются" к нашему результату.

do {
        //Продолжаем  формировать строку поисковой выдачи
        $text .= '<p><a href="http://'.$row['articleId'].'">';
        $text .= $row['title'].'</a></p>';
        $text .= '<p>'.$row['tinyDescription'].'</p>';
        // Делаем это пока у нас есть результаты
      } while ($row = mysql_fetch_assoc($result)); 
    } else {
      // Найти совпадение не удалось 
      $text = '<p>По вашему запросу ничего не найдено.</p>';
    }
  } 
}else {
  $text = '<p>Задан пустой поисковый запрос.</p>';
}

Ну и в конце работы функции возвращаем в главный скрипт результат.

//Возвращаем сформированную строку поисковой выдачи
return $text; 
}

Ну а далее идет блок кода, который по идее должен быть отдельным файлом search.php, и в котором подключаются все наши функции
///////////// Сам скрипт обработчик ///////////////
if (isset ($_POST['query'])){ 
  // Открываем соединение с базой данных
  $connect = connectDB();
  $search_result = search ($_POST['query']); 
  echo $search_result; 
  // Закрываем соединение с  базой данных
  closeDB ($connect);
}
?>

Как вам скриптец? Не поразил размерами? А ведь именно от него все и зависит. Разберем его работу.

Сначала он проверяет существует ли isset() и не пустой ли !empty() пришедший нам методом POST['query'] запрос от клиента (браузера). Если все OK, открываем соединение с базой данных Mysql и вызываем нашу функцию search(), в которую передаем поисковый запрос.

Следующая строка выводит ответ от сервера каким бы он не был.

Ну и конечно, не забываем закрыть соединение с базой данных, передавая ему дескриптор соединения - $connect, после окончания работы.

Простейший поиск по сайту с использованием PHP и MySQL готов. Конечно вы можете модернизировать его по своему усмотрению.

А в статье "Поиск по сайту AJAX + PHP + MySQL (AJAX)" я покажу как расширить скрипт php и подключить подключить к ним AJAX А на сегодня у меня все. А если у вас возникли вопросы - пожалуйста задавайте. До свидания и надеюсь на скорую встречу.

Автор: Сергей Зарубин

Дата: 2012-04-25

Колличество просмотров: 21175

Нравится

Комментарии к заметке:

Комментарий добавил(а): eihwas
Дата: 2013-03-13

Спасибо огромное! Более подробной инструкции в сети нет. Всё работает, всё просто, лаконично и, что главное, благодаря вашим пояснениям, всё понятно.

Комментарий добавил(а): Михаил
Дата: 2013-04-20

Скрипт хороший. Спасибо автору. А нельзя ли сделать подсветку в тексте искомого слова?

Комментарий добавил(а): Сергей Зарубин
Дата: 2013-04-21

Обратитесь к посту "Поиск по сайту jQuery + AJAX + PHP + MySQL", в котором я показал как "подсветить" поисковый запрос в поисковой выдаче и оформить результаты выдачи в виде ссылок.

Комментарий добавил(а): Михаил
Дата: 2013-04-21

спасибо, Сергей, пойду гляну. Динамическая аяксовая выдача просто поразила)) поковыряюсь...

Комментарий добавил(а): Ксения
Дата: 2013-04-29

Одно НО! Когда нажимаешь на кнопку поиск, не выводит: "Пустой поисковый запрос!" Просто пустота.

Комментарий добавил(а): Сергей Зарубин
Дата: 2013-04-30

Вы совершенно правы. Всему виной строка:

///////////// Сам скрипт обработчик ///////////////
if (isset ($_POST['query']) && !empty($_POST['query']))
Сказалась привычка проверять не только на существование но и на пустоту передаваемого параметра.
Поправил.

Комментарий добавил(а): Ксения
Дата: 2013-04-30

Нет, надо так
if ((isset ($_POST['query']) && empty($_POST['query'])) or (isset ($_POST['query']) && !empty($_POST['query'])))

Комментарий добавил(а): Сергей Зарубин
Дата: 2013-05-01

А вот здесь позвольте с вами не согласится
в строке
if ((isset ($_POST['query']) && empty($_POST['query'])) or (isset ($_POST['query']) && !empty($_POST['query'])))
вы предлагаете проверять два взаимоисключающих случая empty() и !empty() и разрешаете их оба. Зачем?

Комментарий добавил(а): Ксения
Дата: 2013-05-01

Не "и", а "или".
Со стракой if (isset ($_POST['query']) && !empty($_POST['query'])) вывод только не пустого запроса.

Комментарий добавил(а): Сергей Зарубин
Дата: 2013-05-01

Ксения, наверное вы не обратили внимания, но после вашего первого справедливого замечания я заменил в коде строчку

///////////// Сам скрипт обработчик ///////////////
if (isset ($_POST['query'] ) && !empty($_POST['query']))
на
///////////// Сам скрипт обработчик ///////////////
if (isset ($_POST['query']))
а уже в функции search() я проверяю $query на пустоту
if (!empty($query)){

Комментарий добавил(а): Алексей
Дата: 2013-11-14

Здравствуйте.
Все супер, спасибо большое. Я хоть и не силет в рнр да и вообще не програмист, так, самоучка. Но мне кажется что тут
$sql = "SELECT `id`, `title`, `description`, `link`
FROM `name_table` WHERE `description` LIKE '%$query%'
OR `title` LIKE '%$query%'";

нехватает 'articleId'
по крайней мере у меня без нее не тянет под ссылку адрес.

Комментарий добавил(а): Евгений
Дата: 2014-03-14

Может, я чего-то не понял? Пользователь ввел в поиск фразу, мы убрали спецсимволы и слепили ее в одно слово без пробелов? Мы ничего не найдем, тем более лайком.
И еще.. для вывода результатов вместо if'a и цикла с постусловием не проще ли использовать сразу цикл с предусловием? Запись будет короче, на мой взгляд

Комментарий добавил(а): Сергей
Дата: 2014-07-14

как сделать выборку по всем таблицам в БД для поиска?

Комментарий добавил(а): Руфина
Дата: 2014-07-18

немного не допонемаю. Слово,которое вводим в поле поиска, должно содержаться в нашей таблице в поле title или в поле description, я правильно понимаю?если оно в таблице есть, то возвращается ссылка на страницу, где есть это слово?

Комментарий добавил(а): Евгения
Дата: 2014-08-01

как сделать выборку по всем таблицам в БД для поиска?

Комментарий добавил(а): Евгений
Дата: 2014-11-24

Здравствуйте, у меня такая ситуация абитуриенты сдали тесты и надо по ФИО сделать выборку с выводом страки с отметками по тестам и ошибками. Как это сделать?

Комментарий добавил(а): Евгений
Дата: 2015-04-23

"И так, приступим" - "итак" пишется слитно в вашем случае..

Комментарий добавил(а): Руслан
Дата: 2015-09-22

Можно описание БД, описание как вводить данные в БД, а то получается только половина описания, а те кто вообще не бум-бум в БД - будут сидеть и думать что ничего не работает.

Комментарий добавил(а): Сергей Зарубин
Дата: 2015-12-09

Существует множество вариантов для выборки данных из нескольких таблиц.
Вот для примера:

SELECT table_1.*, table_2.* FROM table_1, table_1 ON t1.id = t2.id
SELECT * FROM table_1, table_2 WHERE ....
SELECT table_1.*, table_2.* FROM table_1 LEFT JOIN table_2 ON t1.id = t2.id
SELECT table_1.*, table_2.* FROM table_1 LEFT JOIN table_2 USING (id)

Комментарий добавил(а): bonfynk
Дата: 2016-02-08

Спасибо большое. Легко изменил под свои нужды. Все очень понятно и доходчиво. Очень интересно использование в скрипте do while честно не додумался что можно сделать именно так чтобы выводилось несколько записей а не одна.



Добавить новый комментарий


Введите число с картинки:

captcha