Три богатыря – обзор AJAX-библиотек для PHP с практическими примерами
Как известно, писать приложения в идеологии AJAX сложно по многим причинам, начиная довольно трудоемкой отладкой и заканчивая разработкой функций для рутинных действий. А зачем это делать заново, ведь есть готовые библиотеки для PHP!? В этой статье я расскажу о том, как разрабатывать AJAX-приложения, не сходя при этом с ума.
Ищем подопытных
Для этого обзора я выбрал 3 довольно сильно различающихся по функционалу библиотеки. Почему только 3? Дело в том, что другие интересные AJAX-решения обычно являются частью полноценных фреймворков для создания сайтов, поэтому их обзор занял бы слишком много места. Стало быть, о них – в следующий раз, а пока мы познакомимся с участниками сегодняшнего состязания.
Итак, внимание на сцену! Первым выступает представитель легкой весовой категории – Sajax, за ним уверенно двигается крепкий середнячок – Xajax, и, наконец, могучий тяжеловес, жонглер гирями, способный удержать на своей груди платформу с роялем, оркестром и взводом королевских мушкетеров, – Projax.
А что делать-то будем?
Сколько «пустых» статей и других материалов об AJAX и втором поколении веб-технологии публикуются ежедневно? Трудно сосчитать :). В них популярно и доказательно обосновывается, что все это очень круто и прогрессивно, но при этом авторы забывают рассказать нам одну малость – как всего этого добиться. Чтобы не быть голословным, я покажу тебе все это на конкретных примерах, часть из которых ты сможешь сразу использовать на своих веб-сайтах. Начнем с самой простой библиотеки – Sajax.
Sajax
Sajax – довольно простая библиотека, поэтому серверный и клиентский код мы можем (и будем :)) писать в одном файле. Функционал у нашей первой программы будет очень простым: мы нажимаем кнопку, и в текстовое поле загружается текст, разумеется, без перезагрузки страницы.
Для начала сделаем серверную часть, в которой будет экспортироваться функция, возвращающая текст для клиента:
ЯЗЫК: PHP
ОПИСАНИЕ: Серверная часть скрипта< ?php
require(«Sajax.php»);
function hello_world() {
return «Hello, world!»;
}
sajax_init();
// Раскомментировать для отладочного режима
// $sajax_debug_mode = 1;
sajax_export(«hello_world»);
sajax_handle_client_request();
?>
Последняя строка этого скрипта автоматически обрабатывает запросы клиента.
Ну что же, перейдем к клиентской части, которой надо выдать HTML и JavaScript (поместим мы ее в тот же файл, сразу за закрывающимся тэгом PHP).
Для автоматической генерации JavaScript мы воспользуемся библиотечной функцией sajax_show_javascript(), а для асинхронной работы JavaScript – определим функцию do_hello_world, которая будет вызываться при нажатии кнопки, и функцию do_hello_world_callback, которая сработает при получении ответа сервера и положит результат в текстовое поле.
Вся соль библиотеки Sajax кроется в работе do_hello_world, которая вызывает автоматически сгенерированную x_hello_world. Фактически, мы из JavaScript вызываем функцию, которая написана на PHP и хранится на сервере, а в качестве параметра передаем ей функцию обратного вызова:
ЯЗЫК: HTML и JavaScript
ОПИСАНИЕ: Клиентская часть скрипта
<html>
<head>
<title>Hello, world! by sAJAX</title>
<script>
<?php sajax_show_javascript(); ?>
function do_hello_world_callback(result) {
document.getElementById(«return_string»).value = result;
}
function do_hello_world() {
x_hello_world(do_hello_world_callback);
}
</script>
</head>
<body>
<input type=»text» id=»return_string» value=»Здесь будет результат запроса»>
<input type=»button» value=»Послать запрос» onclick=»do_hello_world(); return false;»>
</body>
</html>
Запустим скрипт и посмотрим описание функции x_hello_world, которое автоматически генерируется при вызове PHP-функции sajax_export(«hello_world»):
ЯЗЫК: JavaScript
ОПИСАНИЕ: Функция x_hello_world, сгенерированная библиотекой Sajax
// оболочка для функции hello_world
function x_hello_world() {
sajax_do_call(«hello_world», x_hello_world.arguments);
}
В результате происходит прозрачный вызов PHP-функции, которая хранится на сервере. Теперь попробуем вызвать серверную функцию с параметрами, для чего напишем гостевую книгу, в которую сообщения будут добавляться без перезагрузки страницы, а отображение новых сообщений будет происходить автоматически. Для простоты я предположу, что у нас есть API для работы с сообщениями. Это может быть программный интерфейс к базе данных или XML-хранилищу. В нем нам нужны 3 функции:
«Название функции» и «Описание функции»
messages_api_print_messages() – печать всех сообщений в виде HTML
messages_api_add_message($message) – добавление сообщения
messages_api_get_messages() – возврат всех сообщений в виде HTML
Теперь напишем серверную часть, в которой изменится только описание функции и ее экспорт:
ЯЗЫК: PHP
ОПИСАНИЕ: Серверная часть скрипта<?
require(«Sajax.php»);
require(«messages_api.php»);function add_message($message) {
messages_api_add_message($message);
return messages_api_get_messages();
}
sajax_init();
sajax_export(«add_message»);
sajax_handle_client_request();
?>
На стороне клиента у нас будет поле для ввода текста и кнопка для отправления. Сообщения будут отображаться ниже:
ЯЗЫК: HTML, JavaScript, PHP
ОПИСАНИЕ: Клиентская часть скрипта<html>
<head>
<title>Гостевая книга by sAJAX</title>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<script>
<?php sajax_show_javascript(); ?>
function do_add_message_callback(result) {
document.getElementById(«messages»).innerHTML = unescape(result);
}
function do_add_message() {
message = document.getElementById(«message»).value;
x_add_message(message, do_add_message_callback);
}
</script>
</head>
<body>
<textarea id=»message»></textarea><br />
<input type=»button» value=»Отправить» onclick=»do_add_message(); return false;»>
<hr />
<div id=»messages»>
<?php
messages_api_print_messages();
?>
</div>
</body>
</html>
При нажатии на кнопку «Отправить» вызывается функция x_add_message, которой в качестве параметра передается не только функция обратного вызова, но и содержимое текстового поля. Надеюсь, внимательный читатель обратил внимание и на вызов функции unescape(result) для нормального отображения кириллических символов. Если нет желания каждый раз вызывать ее, можно пропатчить саму библиотеку.
Xajax
Несмотря на то что эта библиотека чуть мощнее предыдущей, работать с ней не намного сложнее. Чтобы быстро войти в курс дела, посмотрим, как можно с помощью Xajax загрузить файл по нажатию кнопки:
ЯЗЫК: HTML, JavaScript, PHP
ОПИСАНИЕ: Загрузка файла при помощи Xajax<?php
require (‘xajax.inc.php’);
function loadFile($file) {
$objResponse = new xajaxResponse();
$objResponse->addAssign(«result», «innerHTML», file_get_contents($file));
$objResponse->addAssign(«result», «style.visibility», ‘visible’);
return $objResponse;
}
$xajax = new xajax();// Раскомментировать для отладки
//$xajax->debugOn();
$xajax->registerFunction(«loadFile»);
$xajax->processRequests();
?>
<html>
<head>
<title>Загрузка файла</title>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<?php $xajax->printJavascript(»); ?>
</head>
<body style=»text-align: center;»>
<button onclick=»xajax_loadFile(‘file.data’)»>Загрузить файл</button>
<div style=»border: 1px solid black; visibility:hidden;» id=»result»></div>
<br/>
</body>
</html>
Первое, что бросается в глаза при прочтении кода, – поддержка ООП в Xajax, ведь мы работаем не с функциями, а с классами и объектами, которые при желании можно расширить. Общая схема работы аналогична Sajax, по-другому идет разве что отправка ответа с сервера клиенту – для этого используется объект $objResponse класса xajaxResponse. Я использовал метод addAssign, который ищет объект HTML с заданным id и определенному полю присваивает нужное значение. То есть мы можем не только прозрачно вызывать серверные функции на клиенте, но и прозрачно модифицировать HTML с сервера (и добавлять JavaScript).
Кстати, помнится, я обещал продемонстрировать, как надо разделять AJAX-систему на клиента и сервер. Настало время исполнить обещание, а заодно – показать, как Xajax умеет автоматически отсылать формы на сервер.
На каждом сайте, который поддерживает создание сетевого сообщества, имеется процедура регистрации с помощью специальной формы. Чтобы зарегистрироваться, надо потратить немало сил: то пароль слишком легкий, то логин занят – проще просто бросить это дело. Попробуем сделать эту процедуру безболезненной, быстрой и интерактивной.
Логин, введенный пользователем, должен быть незанятым и отвечать некоторым требованиям, например состоять более чем из трех символов. На пароль мы наложим только ограничение по длине: 6 символов. Дополнительные проверки можешь придумать сам – все зависит от твоей фантазии ;). Вся система будет содержать 3 файла:
«Имя файла» и «Описание»
register.common.php – общий функционал для клиента и сервера
register.server.php – серверная часть для проверки логина, пароля и обработки формы
register.php – клиентская часть с интерактивной формой ввода
Начнем с общей части для клиента и сервера, в которой будут регистрироваться 3 функции для проверки логина, пароля и для приема данных с клиента. Поскольку серверная часть будет у нас в отдельном файле, это надо указать в конструкторе объекта $xajax:
ЯЗЫК: PHP
ОПИСАНИЕ: register.common.php<?php
require (‘xajax.inc.php’);
$xajax = new xajax(«register.server.php»);
// Раскомментировать для отладки
//$xajax->debugOn();
$xajax->registerFunction(«checkUserName»);
$xajax->registerFunction(«checkUserPass»);
$xajax->registerFunction(«submitForm»);
$xajax->processRequests();
?>
Функции для проверки я предлагаю описать отдельно, так как они будут вызываться у нас в двух случаях: когда форма будет передана на сервер и когда по мере набора текста пользователем будет происходить автоматическая проверка:
ЯЗЫК: PHP
ОПИСАНИЕ: Функции для проверки логина и пароля (register.server.php)function isUserNameGood($userName) {
// Их надо брать из базы
$users = array(«bill», «john», «vasya»);
if (strlen($userName) <= 3)
return array(false, «Имя пользователя должно быть длиннее трех символов»);
foreach ($users as $user)
if ($user == $userName)
return array(false, «Имя пользователя уже используется»);
return array(true, «Имя пользователя подходит»);
}function isUserPassGood($userPass) {
$objResponse = new xajaxResponse();
if (strlen($userPass) <= 6)
return array(false, «Пароль должен быть длиннее шести символов»);
return array(true, «Пароль подходит»);
}
Обе функции возвращают 2 значения, первое имеет булевский тип и определяет, подходят ли логин и пароль соответственно, а второе содержит пояснительный текст. Теперь реализовать функции, которые будут вызываться клиентом, не составит труда:
ЯЗЫК: PHP
ОПИСАНИЕ: Функции, которые будут вызываться из JavaScript (register.server.php)function checkUserName($userName) {
$objResponse = new xajaxResponse();
list($isUserNameGood, $message) = isUserNameGood($userName);
$objResponse->addAssign(«userNameOk», «innerHTML», $message);
return $objResponse;
}
function checkUserPass($userPass) {
$objResponse = new xajaxResponse();
list($isUserPassGood, $message) = isUserPassGood($userPass);
$objResponse->addAssign(«userPassOk», «innerHTML», $message);
return $objResponse;
}
Отмечу, что результат у меня помещается в специальные ячейки в таблице с айдишниками – userNameOk и userPassOk, которые мы опишем на стороне клиента. И последнее, что нам осталось сделать на сервере, – это создать функцию, которая будет обрабатывать данные из формы для регистрации пользователя. Все содержимое передается этой функции в виде параметра, который представляет собой ассоциативный массив (аналог $_POST и $_GET):
ЯЗЫК: PHP
ОПИСАНИЕ: Функция для обработки формы (register.server.php)function submitForm($formData) {
$objResponse = new xajaxResponse();
list($isUserNameGood, $message) = isUserNameGood($formData['userName']);
$objResponse->addAssign(«resultDiv», «innerHTML», $message);
list($isUserPassGood, $message) = isUserPassGood($formData['userPass']);
$objResponse->addAppend(«resultDiv», «innerHTML», «<br/>» . $message);
if ($isUserNameGood && $isUserPassGood)
$objResponse->addAppend(«resultDiv», «innerHTML», «<br/><strong>Регистрация прошла успешно</strong>»);
else
$objResponse->addAppend(«resultDiv», «innerHTML», «<br/><strong>Регистрация завершилась неудачей</strong>»);
return $objResponse;
}
Обрати внимание, что в этих скриптах я нигде не использую базу данных или любое другое постоянное хранилище, чтобы код не потерял ясность. В реальных условиях при успешной регистрации пользователя обязательно надо сохранять его данные, да и получать список пользователей надо тоже из какого-то хранилища. Теперь напишем клиентский код, который будет описывать форму регистрации. Чтобы браузер отправил форму без перезагрузки страницы, нужно «обнулить» (точнее, «завойдить» :)) параметр action у формы и прописать событие onsubmit. При этом событии будет вызвана JavaScript-функция xajax_sumbitForm, которая является оберткой нашей серверной функции submitForm, а параметром будут как раз данные формы. Проверка данных формы во время их набора пользователем осуществляется при помощи вызова соответствующих функций по событию onkeyup:
ЯЗЫК: HTML, JavaScript, PHP
ОПИСАНИЕ: Клиентский код (register.php)<?php
require (‘register.common.php’);
?>
<html>
<head>
<title>Регистрация пользователя</title>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<?php $xajax->printJavascript(»); ?>
<script type=»text/javascript»>
function submitForm() {
xajax.$(‘submit’).disabled=true;
xajax.$(‘submit’).value=»Регистрируется пользователь…»;
xajax_submitForm(xajax.getFormValues(«registrationForm»));
return false;
}
</script>
</head>
<body>
<form id=»registrationForm» action=»javascript:void(null);» onsubmit=»submitForm();»>
<table border=»1″ width=»50%»>
<tr>
<td width=»40%»>Имя пользователя </td>
<td><input onkeyup=»xajax_checkUserName(this.value)» type=»text» id=»userName» name=»userName» /></td></tr>
<tr>
<td id=»userNameOk» colspan=»2″> </td>
</tr>
<tr>
<td width=»40%»>Пароль</td>
<td><input type=»text» onkeyup=»xajax_checkUserPass(this.value)» id=»userPass» name=»userPass» /></td>
</tr>
<tr>
<td id=»userPassOk» colspan=»2″> </td>
</tr>
<tr>
<td> </td>
<td><input type=»submit» id=»submit» value=»Submit» /></td>
</tr>
</table>
<div id=»resultDiv»> </div>
</form>
</body>
</html>
Projax
Настало время десерта – самой мощной библиотеки в нашем обзоре. Я покажу ее возможности на очень распространенном сейчас виджете – поле ввода с автозавершением (a-ля Google Suggest). Для этого у нас есть все необходимое, остается только подключить JavaScript-файлы и вызвать метод text_field_with_auto_complete – на этом клиентская часть заканчивается.
ЯЗЫК: HTML, JavaScript, PHP
ОПИСАНИЕ: Клиентский код – «поле ввода с автозавершением»<?php
include («projax.php»);
$projax= new Projax();
?>
<html>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>Демонстрация автозавершения by Projax</title>
<script src=»js/prototype.js» mce_src=»js/prototype.js» type=»text/javascript»></script>
<script src=»js/scriptaculous.js» mce_src=»js/scriptaculous.js» type=»text/javascript»></script>
</head>
<body>
Введите имя пользователя :<br />
<?=$projax->text_field_with_auto_complete(‘name’, null, array(‘url’=>’get_names.php’));?>
</body>
</html>
Серверная часть будет просто печатать список строк, в котором есть подстрока, набранная пользователем:
ЯЗЫК: PHP
ОПИСАНИЕ: Серверная – «поле ввода с автозавершением» (get_names.php)<?php
// Имена пользователей берутся из базы
$names = array(‘boris’, ‘vasya’, ‘bill’);
foreach($names as $name)
$ret_val .= (strstr($name,$_POST['name'])) ? ‘<li>’.$name.’</li>’:»;
echo ‘<ul>’ . $ret_val . ‘</ul>’;
?>
Как видишь, всего несколько строк кода – и мы уже у цели (посмотри на скрин «Поле с автозавершением» и возрадуйся – у тебя будет такой же :)).
Заключение
В этой статье мы рассмотрели 3 библиотеки, которые позволяют быстро писать эффективные приложения в связке PHP и JavaScript, реализуя таким образом методологию AJAX. Каждая из этих библиотек имеет как плюсы, так и минусы, которые надо знать, чтобы выбрать нужную из них для конкретного проекта. Поэтому мой вердикт таков – срочно бери с диска библиотеки и материалы к этой статье и ковыряй их до выхода в свет следующего «Кодинга» :).
Sajax (www.modernmethod.com/sajax)
Sajax (Simple Ajax Toolkit) – это простая библиотека для создания AJAX-приложений на PHP путем прозрачного вызова серверных функций с клиента. Общий вес клиентского и серверного кода составляет чуть меньше 9 Кб, что делает библиотеку незаменимой для небольших и быстрых приложений. Ее можно посоветовать использовать тем, кто собирается переделывать свое AJAX-приложение без использования фреймворков, поскольку Sajax – довольно низкоуровневая библиотека, не содержащая лишних наворотов. В комплект поставки входят фреймворки для следующих языков: ASP, Cold Fusion, Io, Lua, Perl, PHP, Python и Ruby. К минусам библиотеки можно отнести некорректную работу с кириллицей (правда, проблема довольно просто решается).
Xajax (www.xajaxproject.org)
Для 90% всех веб-проектов хватит библиотеки Xajax, которая обеспечивает полностью прозрачное взаимодействие клиента и сервера (причем в обе стороны). Размер клиентской части в сжатом виде составляет 15 Кб, что вполне приемлемо для библиотеки с таким функционалом. В дистрибутив входят примеры (в том числе XUL-приложение для Mozilla Firefox) и тесты для этой библиотеки. Кроме того, хочу отметить наличие в интернете большого количества документации и сообщества, которое сложилось вокруг этого проекта. По моему очень скромному мнению, эта библиотека является наиболее сбалансированной по параметрам «функционал» и «легкость использования». Выбор редакции, так сказать ;).
Projax (www.ngcoders.com/projax)
Projax представляет собой порт проекта Prototype, который был первоначально написан для Ruby on Rails и проекта script.aculo.us. Такой мощный функционал объясняет общий размер клиентской части – более 170 Кб кода JavaScript. За эти «деньги» мы получаем полную «корзину фруктов» – от манипуляций с DOM до визуальных эффектов. Projax идеально подходит для «суперинтерактивных» проектов, например, онлайн-игр, где нужен мощный функционал на стороне пользователя. Минусом опять же является некоторая сложность этой библиотеки, которую ты, конечно, не заметишь, если раньше работал с Prototype и script.aculo.us
Информация
Библиотеки обычно содержат отладочный режим, при включении которого выдаются сообщения о ходе выполнения программы.
Для эффективной отладки AJAX-приложений необходимо настроить отладку как серверного PHP-кода, так и клиентского JavaScript.
Для отладки JavaScript проще всего использовать расширения для Mozilla Firefox – JavaScript Debugger и FireBug.
Источник: xakep.ru