PHP

Поиск с панелью предложений

В данном уроке мы разберемся, как создать дополнительную функцию для поиска. Идея заключается в том, чтобы при вводе запроса производить поиск по списку отобранных заранее статей (или товаров) и предлагать посетителю подходящие к запросу пункты.

Предложения к поиску

В реализации данного функционала будут задействованы следующие техники: MySQL (база данных), HTML/CSS (разметка страницы и вывод на экран), PHP (для получения данных) и jQuery (для организации запроса AJAX).

В браузерах, которые поддерживают CSS3, результат предложений будет выводиться с тенью.

MySQL

Для работы нам понадобится две таблицы в базе данных. Вот запросы для их организации:
 	CREATE TABLE IF NOT EXISTS `categories` (
 	  `cid` int(11) NOT NULL AUTO_INCREMENT,
 	  `cat_name` varchar(255) NOT NULL,
 	  `cat_url` text NOT NULL,
 	  PRIMARY KEY (`cid`)
 	) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 	 
 	CREATE TABLE IF NOT EXISTS `search` (
 	  `id` int(11) NOT NULL AUTO_INCREMENT,
 	  `cat_id` int(11) NOT NULL,
 	  `name` varchar(255) NOT NULL,
 	  `img` varchar(255) NOT NULL,
 	  `desc` text NOT NULL,
 	  `url` text NOT NULL,
 	  PRIMARY KEY (`id`)
 	) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Структура таблиц достаточно простая и очевидная. Таблица categories содержит категории для пунктов списка предложений, а таблица search содержит сами предложения. В архиве с исходным кодом в файле DATABASE.sql содержатся запросы INSERT для заполнения таблиц.

Теперь рассмотрим интерфейс для работы с таблицами.

HTML

HTML код демонстрационной страницы очень прост. Имеется форма с одним полем ввода, даже без кнопки отправки.
 	<div>
 	    <form id="searchform">
 	        <div>
 	            Что нужно найти? <input type="text" size="30" value="" id="inputString" onkeyup="lookup(this.value);" />
 	        </div>
 	        <div id="suggestions"></div>
 	    </form>
 	</div>

Элемент div suggestions будет заполняться результатами поиска по таблицам с помощью jQuery.

Результат поиска будет иметь следующую разметку:
 	<p id="searchresults">
 	   <span class="category">[КАТЕГОРИЯ_ИЗ_БД]</span>
 	      <a href="[URL_ИЗ_БД]">
 	         <img alt="" src="search_images/[ИМЯ_ИЗОБРАЖЕНИЯ_ИЗ_БД]"/>
 	         <span class="searchheading">[ЗАГОЛОВОК_ИЗ_БД]</span>
 	         <span>[ТЕКСТ_ИЗ_БД]</span>
 	      </a>
 	      <a href="[URL_ИЗ_БД]">
 	         <img alt="" src="search_images/[ИМЯ_ИЗОБРАЖЕНИЯ_ИЗ_БД]"/>
 	         <span class="searchheading">[ЗАГОЛОВОК_ИЗ_БД]</span>
 	         <span>[ТЕКСТ_ИЗ_БД]</span>
 	      </a>
 	      <!-- еще предложения -->
	   <span class="category">[КАТЕГОРИЯ_ИЗ_БД]</span>
 	      <a href="[URL_ИЗ_БД]">
 	         <img alt="" src="search_images/[ИМЯ_ИЗОБРАЖЕНИЯ_ИЗ_БД]"/>
 	         <span class="searchheading">[ЗАГОЛОВОК_ИЗ_БД]</span>
 	         <span>[ТЕКСТ_ИЗ_БД]</span>
 	      </a>
 	   <!-- еще категории -->
 	   <span class="seperator">
 	      <a href="http://evgeniypopov.com/" title="Блог" target="_blank">Нет ничего интересного? Посмотрите на сайте.</a>
 	   </span>
 	</p>

#searchresults - основной контейнер для результатов поиска по списку предложений.
.category - для разделения категорий.
.seperator - используется для ссылки на другой источник.
Все значения между [] будут подставляться из базы данных.

Теперь перейдем к заданию стилей.


CSS
 	/* Элементы HTML */
 	body { font-family:"Lucida Grande","Lucida Sans Unicode",Arial,Verdana,sans-serif;
 	       background-color:#efefef; background-image:url(../images/bg.jpg); }
 	 
 	/* Общие классы */
	.break { clear:both; }
 	 
 	/* Форма поиска */
 	#searchform { margin:50px 200px; font-size:18px; }
 	#searchform div { color:#eeeeee; }
 	#searchform div input { font-size:18px; padding:5px; width:400px; }
 	#suggestions{ position: relative; left:235px; width:400px; display:none; }

Внимание стоит обратить только на #suggestion. мы будем управлять его выводом на экран из JavaScript кода, поэтому изначально он отключен.

Стили для результата поиска предложений несколько сложнее:
 	/* Результаты поиска */
 	#searchresults { border-width:1px; border-color:#919191; border-style:solid; width:400px; background-color:#a0a0a0; font-size:10px; line-height:14px; }
 	#searchresults a { display:block; background-color:#e4e4e4; clear:left; height:80px; text-decoration:none; }
 	#searchresults a:hover { background-color:#b7b7b7; color:#ffffff; }
 	#searchresults a img { float:left; padding:5px 10px; }
 	#searchresults a span.searchheading { display:block; font-weight:bold; padding-top:5px; color:#191919; }
 	#searchresults a:hover span.searchheading { color:#ffffff; }
 	#searchresults a span { color:#555555; }
 	#searchresults a:hover span { color:#f1f1f1; }
 	#searchresults span.category { font-size:11px; margin:5px; display:block; color:#ffffff; }
 	#searchresults span.seperator { float:right; padding-right:15px; margin-right:5px;
 	            background-image:url(../images/shortcuts_arrow.gif); background-repeat:no-repeat; background-position:right; }
 	#searchresults span.seperator a { background-color:transparent; display:block; margin:5px; height:auto; color:#ffffff; }


Панель предложений будет выглядеть следующим образом:

Панель предложений

PHP

Страница с формой поиска - статическая, а панель предложений формируется динамически. Вот полный код PHP, обеспечивающий нужный функционал:
 	<p id="searchresults">
 	<?php
 	    // Реализация PHP5 - используем MySQLi.
 	    // mysqli('localhost', 'имя_пользователя', 'пароль', 'база_данных');
 	    $db = new mysqli('localhost', 'имя_пользователя', 'пароль', 'база_данных');
 	     
 	    if(!$db) {
 	        // Выводим сообщение об ошибке
 	        echo 'Ошибка: Нет соединения с базой данных.';
 	    } else {
 	     
 	        $query = $db->query("SET character_set_connection=utf8");
 	        $query = $db->query("SET character_set_client=utf8");
 	        $query = $db->query("SET character_set_results=utf8");
 	        $query = $db->query("SET NAMES utf8");
 	         
 	        // Есть переданная строка запроса?
 	        if(isset($_POST['queryString'])) {
 	            $queryString = $db->real_escape_string($_POST['queryString']);
 	             
 	            // Строка запроса имеет длину больше, чем 0?
 	            if(strlen($queryString) >0) {
 	                $query = $db->query("SELECT * FROM search s INNER JOIN categories c ON s.cat_id = c.cid WHERE name LIKE '%" . $queryString . "%' ORDER BY cat_id LIMIT 8");
 	                 
 	                if($query) {
 	                    // Пока есть результат запроса, обрабатываем его.
	                     
 	                    // Сохраняем ID категории
 	                    $catid = 0;
 	                    while ($result = $query ->fetch_object()) {
 	                        if($result->cat_id != $catid) { // Проверяем, изменилась ли категория
 	                            echo '<span class="category">'.$result->cat_name.'</span>';
 	                            $catid = $result->cat_id;
 	                        }
 	                        echo '<a href="'.$result->url.'" target="_blank">';
 	                        echo '<img src="search_images/'.$result->img.'" alt="" />';
 	                         
 	                        $name = $result->name;
 	                        if(mb_strlen($name,'UTF-8') > 50) {
 	                            $name = mb_substr($name, 0, 50, 'UTF-8');
 	                            $name .= "...";
 	                        }                      
 	                        echo '<span class="searchheading">'.$name.'</span>';
 	                         
 	                        $description = $result->desc;
 	                        if(mb_strlen($description, 'UTF-8') > 120) {
 	                            $description = mb_substr($description, 0, 120, 'UTF-8');
 	                            $description .= "...";
 	                        }
	                         
 	                        echo '<span>'.$description.'</span></a>';
 	                    }
 	                    echo '<span class="seperator"><a href="http://evgeniypopov.com/" title="Блог" target="_blank">Нет ничего интересного? Посмотрите на сайте.</a></span><br class="break" />';
 	                } else {
 	                    echo 'Ошибка: Есть проблемы с запросом.';
 	                }
 	            } else {
 	                // Ничего не делаем
 	            }
 	        } else {
 	            echo 'Должно быть, у вас нет доступа к данному скрипту!';
 	        }
 	    }
 	?>
	</p>

Несколько пояснений:

isset($_POST['queryString']) - когда PHP файл получает запрос POST с значением queryString, то он будет работать (в противном случае будет выдана предупреждающая надпись). Мы будем формировать запрос POST с помощью jQuery.
mysqli - данный скрипт использует реализацию MySQLi. Мы создаем объект базы данных. Нужно поменять значения (имя пользователя, пароль и название базы данных) для соединения с вашей базой данных.
$db->query - Здесь выполняется запрос. Таблица categories присоединяется для получения названия категории. Поиск выполняется только по полю name. Можно расширить возможности, добавив поиск по описанию.
mb_strlen($name, 'UTF-8') > 50 - в данной точке скрипт проверяет длину имени. Если она больше 50 символов, то мы обрезаем ее и добавляем в конец "...".


jQuery

Нам нужно изменить код так, чтобы браузер реагировал на нажатие клавиш, когда производится ввод текста в поле. Для этого добавим к input следующий код:
 	onkeyup="lookup(this.value);"

Затем определим функцию lookup, в которой будет генерироваться запрос:
 	function lookup(inputString) {
 	    if(inputString.length == 0) {
 	        $('#suggestions').fadeOut(); // Скрываем поле предложений
 	    } else {
	        $.post("rpc.php", {queryString: ""+inputString+""}, function(data) { // Выполняем запрос AJAX
	            $('#suggestions').fadeIn(); // Выводим поле предложений
 	            $('#suggestions').html(data); // Заполняем поле предложений
 	        });
 	    }

Если поле для ввода текста пустое, то панель предложений отключается. При наличии текста формируется запрос AJAX, а результат направляется для вывода на панели предложений.


Готово!
Добавлено: 19 Августа 2013 08:18:17 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...