Ajax Russia : Аякс по-русски

Свежие новости из мира IT

AJAX PHP поиск - часть 2: Prototype

AJAX PHP поиск - часть 2: PrototypeВ первой части урока мы рассмотрели организацию поиска по базе данных MySQL средствами AJAX, PHP и XML. Теперь я хочу показать этот же пример, только с использованием библиотеки prototype. Глобальных изменений не произошло, внешне работает абсолютно одинаково. В конце урока попытаемся подвести небольшую сравнительную характеристику двух этих методов.

Пример: http://logicerror.pp.ru/upload/ajax_search_prototype/

Сравните внешне с предыдущим примером:
http://logicerror.pp.ru/upload/ajax_search_xml/

Элементы всё те же:

  1. база данных MySQL
  2. внешний вид - index.html
  3. ajax скрипт - script.js
  4. php двигатель - search.php
  5. ну и собственно prototype.js

Скачать последнюю версию библиотеки prototype можно здесь: http://www.prototypejs.org/ (оф. сайт библиотеки)

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

MySQL database

База данных у нас осталась без изменений, причем лично я ее и не дублировал, то есть вы можете подключиться к той же базе, что и в предыдущем уроке. Тем кто опоздал дублирую структуру.

SQL:
  1. CREATE TABLE `articles` (
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,
  3.   `title` varchar(255) collate utf8_unicode_ci NOT NULL,
  4.   `content` text collate utf8_unicode_ci NOT NULL,
  5.   `author` varchar(255) collate utf8_unicode_ci NOT NULL,
  6.   `timestamp` int(11) NOT NULL,
  7.   UNIQUE KEY `id` (`id`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;

Ну и, конечно же, моя любимая ссылочка на мусор в базу данных ;) http://logicerror.pp.ru/upload/ajax_search_xml/junk.sql

HTML revised

CODE:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Language" content="ru">
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6. <title>AJAX PHP search example - Prototype</title>
  7.  
  8. <link rel="stylesheet" href="style.css" type="text/css">
  9. <script src="script.js" type="text/javascript"></script>
  10. <script src="prototype.js" type="text/javascript"></script>
  11.  
  12. </head>
  13. <body>
  14. <div id="wrap">
  15. <form onsubmit="search(); return false;">
  16. <input type="text" class="input" id="search_input" value=""> <input type="submit" class="button" id="search_button" value="&raquo; поиск">
  17. </form><br>
  18.  
  19. <div id="search_results">
  20. </div>
  21.  
  22. <div id="searching" style="display: none">
  23.     searching
  24. </div>
  25.  
  26. </div>
  27. </body>
  28. </html>

Здесь мы добавили одну строчку, для подключения библиотеки prototype (естественно при условии того, что файл лежит в том же каталоге, что и index.html):

CODE:
  1. <script src="prototype.js" type="text/javascript"></script>

Стиль поля searching изменился, пришлось вынести этот атрибут (display: none) из каскадных таблиц, а почему я объясню чуть ниже:

CODE:
  1. <div id="searching" style="display: none">

Ну и заголовок странички малость изменили ;)

AJAX "prototyping"

JavaScript:
  1. function search() {
  2.   var sSearch = $F("search_input");
  3.  
  4.   if (sSearch.length <3)
  5.   {
  6.     alert("Запрос должен быть не короче 3-х символов.");
  7.     return false;
  8.   }
  9.  
  10.   $('search_results').hide();
  11.   $('searching').show();
  12.  
  13.   new Ajax.Updater('search_results', 'search.php',
  14.     { method: 'get',
  15.       parameters: { search: sSearch },
  16.       onComplete: function () {
  17.         $('search_results').show();
  18.         $('searching').hide();
  19.       }
  20.     }
  21.   );
  22. }

Коротко, правда? Разбираем.

JavaScript:
  1. var sSearch = $F("search_input");
  2.  
  3. if (sSearch.length <3)
  4. {
  5.   alert("Запрос должен быть не короче 3-х символов.");
  6.   return false;
  7. }

Здесь осталось всё как есть, кроме обращения к текстовому полю с идентификатором search_input. В предыдущем уроке мы использовали родной document.getElementById().value, что в принципе и повторяет оператор $F в библиотеки prototype. Очень удобно и чисто.

JavaScript:
  1. $('search_results').hide();
  2. $('searching').show();

В предыдущем уроке, поле search_results (результаты поиска) мы очищали через свойство .innerHTML. Здесь нам достаточно его спрятать (метод hide()), так как Ajax.Updater() у нас сам очистит это поле в нужный момент.

Ну и показываем поле searching методом .show(). Остановимся здесь на миг. Выше я говорил про атрибут display: none, который пришлось перенести в html из css. Дело в том, что, если этот атрибут хранится в css, то показать блок методом .show() мы не сможем (наверное это особенность prototype ;) ) - пришлось бы использовать .style.display = "block", но так гораздо удобнее, согласитесь...

Далее следует AJAX запрос на обновление (Updater)

JavaScript:
  1. new Ajax.Updater('search_results', 'search.php',
  2.   { method: 'get',
  3.     parameters: { search: sSearch },
  4.     onComplete: function () {
  5.       $('search_results').show();
  6.       $('searching').hide();
  7.     }
  8.   }
  9. );

Уже знакомый нам запрос, ничего сложного. Обновлять будем поле search_results (результаты поиска). Запрашивать будем search.php - наш двигатель. Используем метод GET, передавая переменную sSearch (наш поисковой запрос) в качестве параметра search (получается что-то вроде search.php?search=...).

Ну и прикручиваем обработчик события Complete (готово) - функцию, которая будет прятать строку "ищу" (searching) и показывать поле результатов поиска (search_results). Причем, здесь нам и не нужно ничего добавлять в поле результатов, так как, получив результат, данный вид запроса самостоятельно поместит его в поле search_results. Это особенность запроса на обновление - Ajax.Updater.

PHP двигатель

PHP:
  1. <?php
  2.   $db = mysql_connect("localhost", "root", "");
  3.   mysql_select_db("ajax_search");
  4.   mysql_query("SET CHARACTER SET utf8");
  5.  
  6.   header('Content-type: application/xml; charset=utf-8');
  7.   header('Cache-Control: no-cache');
  8.  
  9.   $sString = mysql_real_escape_string($_GET["search"], $db);
  10.   $sql="SELECT * FROM `articles` WHERE `title` LIKE '%$sString%' OR `content` LIKE '%$sString%' ORDER BY `id` DESC LIMIT 10";
  11.   $rs=mysql_query($sql,$db);
  12.  
  13.   if (mysql_num_rows($rs)> 0)
  14.   {
  15.     while ($row = mysql_fetch_array($rs))
  16.     {
  17.       $content=htmlspecialchars(strip_tags($row["content"]));
  18.       if (mb_strlen($content, "utf-8")> 250) $content = mb_substr($content, 0, 250, "utf-8") . "...";
  19. ?>
  20. <div class="result">
  21.     <h1><?=htmlspecialchars($row["title"]);?></h1>
  22.     <?=$content;?>
  23. </div>
  24. <?
  25.     }
  26.   }
  27.   else
  28.   {
  29. ?>
  30. <div class="result">
  31.     <h1> </h1>
  32.     Ничего не найдено
  33. </div>
  34. <?
  35.   }
  36. ?>

В php у нас тоже мало чего изменилось, а именно представление данных. В предыдущем уроке мы использовали XML, а здесь мы используем уже готовый для вывода HTML. Надеюсь вопросов не возникнет. (Не забудьте вместе с XML убрать и его заголовки).

Кстати Content-type советую оставить application/xml, т.к. некоторые браузеры до сих пор не любят ajax запросы к иным форматам.

Вот и всё. Ниже подведена сравнительная характеристика двух методов.

XML vs. Prototype

XML

  • Общий размер: 16 кб
  • Строк кода: 181
  • Время написания: ~2ч.

Prototype

  • Общий размер: 144 кб
  • Строк кода: 141
  • Время написания: ~1ч.

Если кто-нибудь еще и скорость выполнения проверит - дайте знать.

Размер указан без учета каких-либо методов сжатия.

Отсюда следует вывод. Написание самой такой системы, конечно же легче с использованием prototype, тем самым вы избавляете себя от лишнего парсинга. Тем не менее, потратив чуть больше времени, можно уменьшить объем конечного результата в 9 раз, ну естественно если вы не использовали prototype в другом месте на своей странице (наверное нужно все эти библиотеки уже начать интегрировать в браузеры, и чтобы само-обновлялись).

Ну и конечно же, это еще и дело вкуса ;)

Полезные ссылки

Оригинал статьи: AJAX PHP поиск - часть 2: Prototype

del.icio.us Забобрить!

16 Comments so far

  1. Гвидон Маляров April 28th, 2008 11:11

    По моему мнению не стоило мешать в посиковом PHP-движке сам функциаонал поиска и элементы представления. Логичней на мой взгляд сделать js-функцию для преобразования “сырых” результатов поиска из json/xml в html, который затем и будет показан.

    хотя кончено здесь можно уповать на то что приложение совсем небольшое:)

  2. Константин April 28th, 2008 11:57

    Гвидон Маляров, согласен. В первом уроке мы рассмотрели представление поисковых результатов в виде XML (с помощью php), а разбор полётов и показ уже на js был. Здесь я попытался показать как можно обойти XML и вывести сразу в HTML без дополнительного парсинга. JSON мы рассмотрим буквально на днях…

  3. Экономист April 28th, 2008 14:53

    Хорошие анализ урока ! Зачёт !

  4. Владимир April 28th, 2008 18:22

    По поводу размера. Если я не ошибаюсь, 144кБ prototype занимает в несжатом виде.
    Можно значительно уменьшить размер если сжать с помощью JSMin и потом заархивировать gzip (такие архивы поддерживаются большинством браузеров, но можно сделать простую проверку в .htaccess и если браузер не поддерживает gzip отправлять ему несжатый файл).

  5. Константин April 28th, 2008 18:24

    Написано же “Размер указан без учета каких-либо методов сжатия.” ;)

  6. Александр April 28th, 2008 20:47

    Кстати, вот ещё оптимизация. Может и ненужная, но всё таки напишу:

    вместо

    $(’search_results’).show();
    $(’searching’).hide();

    можно сделать так

    $(’search_results’, ’searching’).invoke(’toggle’);

  7. алекс April 29th, 2008 12:29

    $sql=”SELECT * FROM `articles` WHERE `title` LIKE ‘%$sString%’ OR `content` LIKE ‘%$sString%’ ORDER BY `id` DESC LIMIT 10″

    лучше использовать match against
    и полнотекстовый поиск. по большой бд твой лайк свалится как лейк :)))

  8. Константин April 29th, 2008 12:42

    Алекс, видимо вы кое-что упустили: http://www.ajaxrussia.com/archives/ajax-php-search-xml ;)

  9. Жилинский April 29th, 2008 15:20

    Спасибо, быстро и просто прикрутилось к каталогу IT-блогов ( http://kollegi.zhilinsky.ru/ ). Там монстроидальная главная страница, её нельзя перезагружать, поэтому аджакс-решение оказалось очень к месту :-)

  10. Константин April 29th, 2008 15:49

    Жилинский, рад что нашли применение ;) классно получилось, вы молодец

  11. Александр April 30th, 2008 00:50

    Жилинский, классный проект - “коллеги”. Попадаются интересные статьи, которые так бы никогда не нашёл.

  12. Константин April 30th, 2008 10:43

    Да, и по запросу ajax мы на первом месте :)

  13. djon May 11th, 2008 13:58

    отличненько, только вот меня до сих пор мучает вопрос, как сделать “живой” поиск? тоисть чтобы поиск запускался через определенное время, после введения данных в поле, без нажатия по кнопке

    видел такое на некоторых форумах, хочу себе такую же тему прикрутить

  14. Константин June 12th, 2008 09:55

    djon, это делается очень просто. Советую глянуть событие onChange для поля ввода, ну а задержечку сделать можно функцией setTimeout (http://www.htmlite.com/JS018.php)

    Ну и далее смотрите что ввели, пробиваете по базе и выводите ;)

  15. [...] AJAX PHP поиск - часть 2: Prototype [...]

  16. Таракан July 17th, 2008 07:34

    Вполне хорошо.

Leave a reply