Интегрированные среды для работы с PHP: Часть 4. Поддержка Ajax

Как Zend Framework, CakePHP и symfony обрабатывают традиционный код и библиотеки сторонних разработчиков

Ранние версии PHP обычно критиковали за отсутствие поддержки MVC-архитектуры (Model-View-Controller - Модель-Представление-Контроллер). В настоящее время разработчики могут выбрать для работы одну из нескольких интегрированных сред PHP. В данной серии статей "Интегрированные среды для работы с PHP" (EN) рассматриваются три популярные среды (Zend, symfony и CakePHP), исследуются их сходство и отличия при создании и расширении примера приложения. В первой части была очерчена тематика серии и предпосылки использования этих трех интегрированных сред. Во второй части мы создали пример приложения в каждой из них. В третьей части мы расширили приложение и рассмотрели исключения из правил. Здесь, мы разберемся, как в каждой из этих интегрированных сред поддерживается технология Ajax.

О данной серии статей

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

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

Во второй части мы рассмотрим процесс создания примера приложения в каждой из трех интегрированных сред, выделяя их сходства и отличия.

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

Четвертая часть в основном посвящена поддержке Ajax. Рассматривается использование Ajax (родного кода и библиотек сторонних поставщиков), в частности, как каждая из интегрированных сред работает с популярными библиотеками.

В пятой части рассматривается работа вне интегрированных сред. Ставится одна задача (еженощное обновление сценария) и рассматривается процесс ее выполнения в каждой интегрированной среде.


О данной статье

В данной статье рассказывается, как каждая интегрированная среда поддерживает технологию Ajax. Мы расширим приложение Blahg и добавим элементарную функциональность ранжирования сообщений в каждой интегрированной среде, для того чтобы получить определенный практический опыт.

Подразумевается, что вы уже изучили первую, вторую и третью части данной серии статей, в которых рассматривались установка, предварительные требования, процедура создания первоначального приложения и его расширение в каждой интегрированной среде. Если это не так, вам следует прочитать их.


Ajax в Zend Framework

В Zend Framework в настоящее время нет какой-либо интегрированной поддержки Ajax. Существует несколько библиотек в Zend Framework, которые можно использовать для добавления Ajax в ваши приложения, например, Zend_Json и Zend_XmlRpc. Имеются также библиотеки, включенные в Zend Framework, которые помогают воспользоваться преимуществами существующих Web API для популярных приложений, например, Flickr. Но если нужно добавить функциональность Ajax в ваше приложение в Zend, необходимо сделать это самостоятельно.

Плохая новость состоит в том, что нужно написать дополнительный код, чтобы получить желаемые результаты. Хорошая новость - поскольку отсутствует интегрирование с конкретной Ajax-библиотекой, вы можете выбрать любую понравившуюся библиотеку (или вовсе работать без них) и создать Ajax-функциональность любым приемлемым способом.


Ajax в symfony

Интегрированная среда symfony поставляется с библиотеками Prototype и script.aculo.us. Во второй части данной серии статей, инициализируя проект и копируя содержимое Web-каталога в каталог /column/protected/symfony, мы перемещали копию этих библиотек в место, откуда их можно будет использовать в приложении (вам следует это проверить; они должны находиться в каталоге /column/htdocs/symfony/sf/prototype/js/).

Обеспечивая интеграцию с Prototype, среда symfony может предоставить некоторые вспомогательные средства для уменьшения объема ручного кодирования функциональности Ajax в приложении Blahg. Но есть и обратная сторона: если нужно сделать что-то за рамками возможностей Prototype, это нужно сделать самостоятельно.


Ajax в CakePHP

CakePHP предоставляет интеграцию для библиотек Prototype и script.aculo.us. Необходимо загрузить все библиотеки, которые мы хотим использовать (поместить их в каталог /column/htdocs/cakephp/js). На самом деле нам нужна только библиотека Prototype, для того чтобы использовать вспомогательные средства для Ajax. Библиотека script.aculo.us предназначена для более красивого оформления проделанной работы.

Как и в symfony, предоставляя интеграцию с Prototype, CakePHP облегчает жизнь, когда дело касается создания Ajax-функциональности в приложении Blahg. Но обратная сторона остается: если нужно сделать что-то за рамками возможностей Prototype, это нужно сделать самостоятельно. Вспомогательные средства Ajax не помогут.

Примечание. Если вы предпочитаете работать с библиотекой JQuery, используйте вспомогательные средства CakePHP JavaScript. В результате получается довольно изящный код, если все сделано правильно. Но данная тема выходит за рамки нашей статьи.


Настройка базы данных

Начнем с создания таблицы для хранения рейтинга сообщений. Используйте одно и то же SQL-выражение для создания этой таблицы в каждой из трех баз данных.

Листинг 1. Создание таблицы для хранения рейтингов сообщений
CREATE TABLE 'ranks' ( 
'id' INT( 10 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
'post_id' INT( 10 ) NOT NULL ,
'rank' INT( 10 ) NOT NULL 
) ENGINE = MYISAM ;

Примечание. Нам не нужна целая таблица для хранения только рейтингов сообщений. Можно было бы использовать еще один столбец в таблице posts, если изменить способ обновления модифицированного столбца. Нам не нужно передавать модифицированные данные каждый раз, когда кто-то указывает рейтинг сообщения. Но в зависимости от того, как спроектировано приложение Blahg, MySQL или интегрированная среда будет делать именно это. Кроме того, если потребуется делать с рейтингами что-то еще, например, хранить счетчик изменений рейтингов или времени последнего указания рейтинга сообщения, помещение их в отельную таблицу будет иметь смысл.


Добавление рейтингов сообщений в приложение Blahg в среде Zend

Мы должны решить, что использовать для обработки Ajax-запросов. Возможно, мы без каких-либо затруднений сможем реализовать наше собственное решение, но для целей данной статьи каждая интегрированная среда будет использовать библиотеку Prototype (см. раздел "Ресурсы"). Мы должны создать каталог для хранения библиотеки - такой, к которому можно обратиться из браузера, например, /column/htdocs/zend/scripts/ (именно этот каталог используется в архиве исходного кода).

Необходимо создать базовую модель для рейтингов под названием Ranks.php. Она должна быть просто оболочкой модели, как это было сделано для сообщений и комментариев. И, естественно, необходимо создать контроллер ranks. Мы не будем создавать какие-либо представления - контроллер будет просто выводить результаты всех запросов rank. Нам понадобятся два действия: readAction будет искать рейтинг сообщения, а writeAction будет передавать рейтинг для записи и проверять наличие строки для этого сообщения в таблице. Если она существует, рейтинг будет обновляться новым значением; в противном случае будет вставляться новая строка с рейтингом. В любом случае новый рейтинг будет выводиться, для того чтобы можно было обновить рейтинг в представлении. Все это довольно очевидно и может быть найдено в архиве исходного кода. Теперь нам нужно реализовать Ajax в представлениях.

Вспомните, что мы не хотим добавлять сюда какие-либо представления, предназначенные для отображения рейтингов. Но нам понадобится изменить представление для чтения сообщения и включить в него Ajax-код. Откройте файл /column/protected/zend/views/scripts/post/read.php. В нем мы выполним всю нашу работу. Для начала нужно включить библиотеку Prototype в заголовок: <script type="text/javascript" src="/zend/scripts/prototype.js"></script>.

Перед написанием какого-либо JavaScript-кода поместите в нужное место еще кое-что. Нам нужно отобразить текущий рейтинг. В рейтинге при помощи тега span установите ID, для того чтобы можно было обновить значение рейтинга по запросу. Например: <h4>Rank: <span id="rank"></span></h4>.

Затем понадобится пара кнопок (ссылки тоже подойдут), которые может нажать пользователь для указания того, понравилось ему сообщение или нет. Дайте им оригинальные названия, имеющие смысл. Поместите их ниже рейтинга: <input type='button' onclick='rankUp();' value='Hot' /> or <input type='button' onclick='rankDown()' value='Not' />.

Для того чтобы сделать скрытое поле ввода post_id более доступным для Prototype, укажите ID post_id для этого поля.

И, наконец, добавьте событие onLoad в тело для получения текущего рейтинга: <body onload='fetchRank();'>.

Не удивительно, что нужно написать три JavaScript-функций: rankUp, rankDown и fetchRank. Они будут выполнять Ajax-запросы. Эти функции довольно просты и выглядят во многом также, как и в других интегрированных средах. Поместите эти функции в строфу <script> заголовка.

Листинг 2. Три JavaScript-функции
        function fetchRank() {
                var ajax = new Ajax.Request(
                        '/zend/rank/read',
                        {
                                method : 'get',
                                parameters : {'post_id' : $('post_id').value},
                                onComplete: parseRank
                        }
                );
        }
        function rankUp() {
                var ajax = new Ajax.Request(
                        '/zend/rank/write',
                        {
                            method : 'get',
                            parameters : {'post_id' : $('post_id').value, 'rank' : '1'},
                            onComplete: parseRank
                        }
                );
        }
        function rankDown() {
                var ajax = new Ajax.Request(
                        '/zend/rank/write',
                        {
                           method : 'get',
                           parameters : {'post_id' : $('post_id').value, 'rank' : '-1'},
                           onComplete: parseRank
                        }
                );
        }

Каждая функция вызывает parseRank по завершении работы. Эта функция просто принимает любой ответ от Ajax-запроса и помещает его в созданный ранее тег span рейтинга.

Листинг 3. Вызов функции parseRank
        function parseRank(trans) {
                $('rank').innerHTML = trans.responseText;
        }

После выполнения всех этих изменений или импорта их из архива кода мы должны уметь читать сообщение в Blahg и менять его рейтинг. Можно даже схитрить и повышать рейтинг сообщения много раз подряд. Все это мы сделали в Zend. Что нужно сделать для получения аналогичной функциональности в symfony?

Примечание. Возможно, больший смысл имело бы использование Ajax.Updater вместо Ajax.Request. Попробуйте выполнить рефакторинг кода, если являетесь новичком в Ajax.


Добавление рейтингов сообщений в приложение Blahg в среде symfony

Для добавления рейтингов сообщений в symfony начните со схемы schema.yml (она должна находиться в каталоге /column/protected/sf_column/config) и определите таблицу ranks.

Листинг 4. Добавление рейтингов сообщений в symfony
  ranks :
    _attributes: {phpName: Rank }
    id:
    post_id:
    rank:    integer

Помните: необходимо отступить два пробела для ranks и четыре пробела для определений поля.

Что дальше? Создайте модель propel и очистите кэш. Не забудьте в symfony выполнить команды из каталога /column/protected/sf_column (корневой каталог вашего приложения).

Листинг 5. Создание модели propel и очистка кэша
php /column/src/symfony/data/bin/symfony propel-build-model

php /column/src/symfony/data/bin/symfony clear-cache

После выполнения этих команд мы увидим файлы Rank.php и RankPeer.php в каталоге /column/protected/sf_column/lib/model. Теперь пойдем дальше и проинициализируем модуль ranks: php /column/src/symfony/data/bin/symfony init-module blahg rank.

Класс действий rank (/column/protected/sf_column/apps/blahg/modules/rank/actions/actions.class.php) будет содержать два действия: executeRead и executeWrite. Сразу после чтения или обновления рейтинга мы отображаем его, вызывая выход в конце каждого действия (это предохраняет symfony от поиска ассоциированных шаблонов представлений, которые нам не нужно создавать). Просмотрите реализацию этих действий в архиве кода.

Наконец, необходимо обновить шаблон сообщения readSuccess (/column/protected/sf_column/apps/blahg/modules/post/templates/readSuccess.php) для использования вспомогательной JavaScript-функции symfony и включения некоторых Ajax-ссылок. Начнем с добавления следующей строки в начало файла: <?php use_helper('Javascript') ?>. Эта строка включит библиотеку Prototype и предоставит нам доступ к широкому набору вспомогательных классов Ajax. Мы можем использовать один из них для создания вызова загрузки первоначального рейтинга и пары ссылок, которые будут передавать рейтинги. Не забудьте добавить span для отображения текущего рейтинга.

Листинг 6. Создание вызова загрузки первоначального рейтинга
<h4>Rank: <span id="rank"></span></h4>
<?php echo javascript_tag(remote_function(array('update' => 'rank', 
                                   'url' => 'rank/read?post_id=' . $id))) ?>
<?php echo link_to_remote('Hot', array('update' => 'rank', 
                    'url' => 'rank/write?post_id=' . $id . '&rank=1')) ?> or
<?php echo link_to_remote('Not', array('update' => 'rank', 
                       'url' => 'rank/write?post_id=' . $id . '&rank=-1')) ?>

Это все, что нам нужно сделать. Говоря иначе, на самом деле нам не нужно писать какой-либо JavaScript-код. Вспомогательные классы интегрированной среды symfony делают это за нас. Не верите? Настройте все так, как описано выше (или установите код из архива кода) и прочтите сообщение в symfony-версии приложения Blahg. Затем просмотрите исходный код. Разве вы писали весь этот JavaScript?


Добавление рейтингов сообщений в среде CakePHP

Перед добавлением функциональности рейтингов сообщений в CakePHP-версии приложения Blahg убедитесь в том, что загрузили Prototype в каталог /column/htdocs/cakephp/js. Необходимо будет изменить шаблон схемы по умолчанию и включить библиотеку в заголовок. Это файл default.ctp в каталоге /column/protected/cakephp/app/views/layouts/. Добавьте следующую строку в заголовок: <?php echo $javascript->link('prototype') ?>.

Затем нужно создать базовый контроллер AppController, включающий вспомогательные классы JavaScript и Ajax, которые понадобятся ниже. Создайте файл app_controller.php в каталоге /column/protected/cakephp/app. Он должен выглядеть так, как показано в листинге 7.

Листинг 7. Создание файла app_controller.php
<?php

class AppController extends Controller {
        var $helpers = array('Html', 'Form', 'Javascript', 'Ajax');
}
?>

Примечание. Технически это неверно. Мы могли бы использовать эти вспомогательные классы в контроллерах posts и ranks, но создание базового контроллера app позволяет нам использовать их в любом контроллере, не добавляя в список вспомогательных объектов. Это правильный способ перегрузки базового объекта AppController.

Теперь необходимо создать базовую модель ranks и контролер ranks. Они более или менее похожи на модели и контроллеры, которые мы уже создали. При создании модели rank мы должны настроить ассоциации между моделями rank и post. Не обязательно добавлять ассоциацию модели в ranks до тех пор, пока мы не решим впоследствии добавить более надежную функциональность рейтингов. В архиве кода обе ассоциации настроены для формы.

С позиций здравого смысла в контроллере ranks нам нужна пара новых штучек. Необходимо включить использование компонента RequestHandler и добавить функцию beforeFilter. В функции beforeFilter мы проверяем RequestHandler и, если запрос идет через Ajax, отключаем отладочный код. Во всем остальном контроллер выглядит так, как вы, вероятно, ожидаете. Два метода, read и write, ищут post_id и выводят рейтинг.

Примечание. Код контроллера в архиве исходного кода просто возвращает рейтинг, но если делать более сложные Ajax-вызовы, то можно создать шаблон (например, views/ranks/viewrank.ctp) и визуализировать представление, используя $this->render('viewrank', 'ajax');. Но поскольку нам нужен только текущий рейтинг, это излишество.

Теперь осталось только добавить span rank и пару Ajax-ссылок в представление чтения сообщений.

Листинг 8. Добавление span rank
<h4>Rank: <span id="rank"><?php echo (int) $post['Rank']['rank'] ?></span></h4>
<?php echo $ajax->link('Hot', '/ranks/write/' . $post['Post']['id'] . '/1', array
('update' => 'rank')); ?> or
<?php echo $ajax->link('Not', '/ranks/write/' . $post['Post']['id'] . '/-1', array
('update' => 'rank')); ?>

Эти Ajax-ссылки означают "вызвать этот URL через Ajax и обновить DOM-элемент rank полученным результатом, какой бы он ни был" (хорошо, что мы отключили отладочные сообщения). Теперь, когда все находится на своем месте, загрузите сообщение и попробуйте поработать с ним. Взгляните на исходный код и задумайтесь над тем, что нам не пришлось писать весь этот JavaScript-код. Здорово, не правда ли?


Резюме

Вы должны иметь общее представление о том, как каждая интегрированная среда обеспечивает (или не обеспечивает) поддержку Ajax. Попробуйте поработать с более сложным Ajax-кодом. Полученная в данной статье информация должна помочь вам в этом.


Загрузка

ОписаниеИмяРазмер
Пример кода для части 4os-php-fwk4.zip30 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • Prototype - это интегрированная среда JavaScript, облегчающая разработку динамических Web-приложений.
  • Загрузите PHP V5.2.3.
  • Разработайте ваш следующий проект с открытым исходным кодом, используя пробное программное обеспечение IBM, доступное для загрузки или на DVD.(EN)
  • Загрузите оценочные версии продуктов IBM и используйте инструментальные средства разработки приложений и программы промежуточного уровня DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.(EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


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

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=350218
ArticleTitle=Интегрированные среды для работы с PHP: Часть 4. Поддержка Ajax
publish-date=11062008