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

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

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

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

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

demosourse

 

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, а результат направляется для вывода на панели предложений.

 

Готово!

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.marcofolio.net/webdesign/a_fancy_apple.com-style_search_suggestion.html
Перевел: Сергей Фастунов
Урок создан: 25 Января 2011
Просмотров: 33711
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

    Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

    Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 25 Января 2011 18:04
    Алёшко Безправный
    А это нормально что на нажатие клавиши мы имеем 5 запросов к бд 10 символов = 50 запросов 10 пользователей по 10 символов = 500 запросов или я чего то не понимаю или что-то тут не то
    • 25 Января 2011 20:12
      Constantine
      никто писать совершенство тут не будет скрипт функционален для средних малых сайтов усовершенсвовать надо однозначно
  • 25 Января 2011 19:45
    da_lamber
    Классная вещь. Почти как google.
    • 25 Января 2011 22:05
      skript11
      Иму к google дак мне до космаса
      • 25 Января 2011 22:54
        da_lamber
        Не знаю как тебе до чего, но суть похожа
  • 25 Января 2011 22:00
    rekon
    нужная вещь, спс автору
  • 26 Января 2011 00:17
    alexxhub
    странно но у меня вместо вывода необходимых элементов куча ошибок обращения к базе данных.
  • 26 Января 2011 05:56
    SaimonS
    Сайт и его автор уже давно потерял интерес, и занялся чисто коммерцией, понятно что к этому стремиться надо, но надо учитывать кого и чем ты учишь! Вот например вот этот урок переведен Сергеем Фастуновым, Попов хоть выдел что выкладываете. Здесь уроков собственного производства хрен найдешь, один из тысячи. Чисто копипаст с транслитом. Короче сдулся Попов Женя: --- Сначала человек работает на свое имя -&amp;gt; потом имя работает на человека, судя по комментам половина Вас пинают, а Вам похеру. И причем я знаю что этот коммент скорее всего удалишь, зато сам прочитаешь-)))
    • 26 Января 2011 06:05
      Евгений Попов
      А зачем мне удалять? Если тебе этот сайт не интересен, просто не ходи на него. А попробуй создать свой сайт и публикуй там уроки собственного производства. Вот я и посмотрю на какой день ты "сдуешься".
      • 1 Октября 2011 18:15
        Xasler
        +100, верно подметил
    • 26 Января 2011 08:00
      alexxhub
      Скажу по своему опыту, создали сайт - написали порядка 300 своих собственных уроков. В итоге теперь тоже переводим со сторонних ресурсов, т.к. есть уже готовые решения, но не доступные большинству русскоязычного населения, т.к. многие не знают ни английского, ни немецкого. И дело не в коммерции и в том, чтобы предоставлять истинно авторские уроки, а в том, чтобы предоставлять людям информацию. И если есть для этого возможность почему нет? И каждый человек в то же время хочет от своих действий получить какую то отдачу. А Евгений за то время пока авторы сайта переводили достаточно интересные материалы и готовили свои выпустил замечательный диск, за который ему уже многие сказали спасибо. Интересно посмотреть, что ты сделал за это время?
    • 26 Января 2011 10:47
      sdbeet
      SaimonS Ты очень не прав! Зачем придумывать велосипед, если он уже придуман! Он просто не нашего производства!
    • 8 Февраля 2011 22:07
      SilverLight
      SaimonS. Человек платит деньги авторам, перевода уроков, чтобы такие как ты обучались, и ему за это нужно сказать Спасибо!
    • 9 Февраля 2011 07:00
      Mr_Shadow_A
      Для SaimonS. Мне всегда было интересно, - почему каждый дебил тебе подобный, считает себя умником?! Не ответишь? А что касается сайта Евгения, - попробуй собрать полезную информацию на одном ресурсе, а мы посмотрим на что ты горазд. ))) Без уважения к тебе подобным, Артем.
  • 26 Января 2011 17:28
    legonavt
    На критику и притом конструктивную.Думаю имеет право только профи высокого класса,а не понятно кто совсем(и скорее из-за зависти что нет у него такого ресурса).Реально скажу это один из самых лучших ресурсов по данной тематике в русскоязычной зоне инета!Полезен и информативен!С него много можно подчерпнуть.Хотя и в английском тоже не плохо разбираюсь.
  • 27 Января 2011 07:20
    Anabol1k
    <script type="text/javascript" src="http://www.google.com/jsapi"></script> а есть ли локальная библиотека для данного скрипта?
    • 27 Января 2011 18:04
      legonavt
      так можно же скачать оттуда.
      • 28 Января 2011 09:18
        Anabol1k
        он ссылается на гугл, а в этой библиотеке jsapi также имеется много ссылок на удалённые библиотеки google.loader.ServiceBase = 'http://www.google.com/uds'; google.loader.GoogleApisBase = 'http://ajax.googleapis.com/ajax'; Дело в том что я хотел его попытаться прикрутить в локальной сети... без доступа в internet
  • 27 Января 2011 18:35
    skolozhabskiy
    добрый вечер. данный скрипт не работает в IE, пробовал 7 и 8 версии. Кто-нибудь сталкивался с подобной проблемой? Как можно ее решить, скрипт поиска очень интересный. Спасибо за ответ.
  • 28 Января 2011 08:28
    bakha123
    Помогите пожалуйста решить проблему! Как ограничить количество информации на одной странице документов? То есть чтоб не было так много а 10 к примеру, остальное разбивалось и шло на другие страницы
    • 29 Января 2011 16:36
      m4a1fox
      LIMIT - и ограничивай себе сколько надо!?))
  • 9 Февраля 2011 20:31
    zak21
    Евгений, сделай ПЛИЗЗ урок по поиску на сайте, ну, например, такой как на Ruseller.com
    • 24 Февраля 2011 20:55
      OVIK
      zak21, сделай ПЛИЗЗ урок по поиску на сайте, ну, например, такой как на yandex.ru ?
  • 1 Марта 2011 18:09
    Ygreec
    Евгений, скажите пожалуйста, что надо сделать, чтобы этот прекрасный скрипт работал? Я разместил на площадке с поддержкой ПХП, чтобы отладить под свои нужду, но видимо или скрипт не исполняется, или не знаю в чем дело... Надо ли делать еще что-либо кроме размещения в директориях домена? надо ли что-то мудрить с движками или что-то еще? Очень прошу ответить, так как большая необходимость в такой форме поиска. И еще вопрос - это подходит для очень большой базы данных? Заранее благодарен.
  • 26 Марта 2011 11:45
    Ygreec
    Ребята, очень большая просьба, ответьте пожалуйста. Файл rpc.php который и осуществляет поиск по БД, почему-то не выполняется. Хостер Мастерхост с поддержкой ПХП 5.2 Как бы отладить пхп-файл, чтобы работал? И еще - годится ли этот поиск для очень большой БД(порядка 200 тысяч единиц поиска)?
  • 16 Мая 2011 21:23
    depict
    $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");
    можете подробно описать этот код
    • 7 Августа 2011 22:02
      amvlegend
      Код делает выборку из обедненных таблиц. А именно выбирает то что соответствует содержимому переменной за объединение отвечает INNER JOIN. Про LIKE почитайте в MySQL справочнике. С сортировкай по категориям в алфавитном порядке.
  • 7 Августа 2011 21:58
    amvlegend
    Поиск КЛАССНЫЙ пасиб автору). Работает если немного по колдовать. В IE работает так что не нада. Если много ошибок в базе с делайте свой запрос попустит. А сам Евгений Попов маладец спасибо огромное полезный сайт, так держать!!!
  • 16 Августа 2011 20:38
    a777d2
    Евгений у меня вопрос, а как сделать чтобы таблица вывода информации, после вывода не пропадала, а оставалась?
  • 6 Сентября 2011 20:31
    Beswww
    Скажите пожалуйста куда добовлять вторую часть HTML кода начинается <p id="searchresults">... заранее спасибо!
  • 4 Октября 2011 12:58
    SashaKKKKK
    Как сделать чтоб при нажатии не вариант слово вписывалось в само поле. Заранее блегодарен. Алёшко Безправный Это лучший вариант который я вообще нашел, гугл и яндекс обрыл а тут случайно нашел. По поводу запросов то можно и меньше сделать. В лбом случаи вы всегда можете предложить свой вариант.
  • 12 Апреля 2012 20:05
    zoomeron
    Помогите исправить кодировку. Скрипт возвращает каракули.
  • 20 Октября 2013 18:50
    evil_adge
    Хороший поиск. Очень капризный, но если потратить время и настроить то вполне годная вещь получается.
  • 17 Мая 2014 17:21
    igor_khimich
    Бесконечная загрузка страницы в firefox 28.0 Работает только в Safari
^ Наверх ^