Symfony Symfony – это мощный опен-сорсный PHP фреймворк. На сайте проекта можно найти множество статей (перевод одной, вы сейчас читаете), видео-примеры, обширную документацию и достаточно объемную книгу, доступную on-line. Одна особенность статьи, что пример разработки, ведется на unix-like системе, думаю, это никого не испугает, а наоборот привлечет внимание. Обзор В symfony есть Ajax хелпер, который позволяет очень быстро и просто создавать продуманные пользовательские интерфейсы. Это руководство покажет, как шаг за шагом создать Ajax-powered приложение, используя symfony, всего за 10 минут. Вступление Для лентяев, которых утомляет чтение, есть видео-пример, который показывает ниже изложенные действия. Добавление позиции в корзину покупок в электронной торговли не очень близка к фактическому добавлению в корзину, поскольку требуется нажать на ссылку «добавить в корзину», просмотреть открывшуюся страницу (“корзина”), а после вернуться на страницу с товаром. Ajax позволяет приблизить метафорическое добавление товара в корзину в Интернет магазине к фактическому (как например вы это делаете в супермаркете). Подобный эффект достигается добавлением drag&drop возможности и моментальной перерисовки вышей корзины. Описываемы в статье пример является портом примера корзины на сайте script.aculo.us. В примере используется JavaScript фреймворк prototype (который входит в состав symfony) и несколько скриптов из библиотеки script.aculo.us, которые входят в состав JavaScript хелпера. Настройка Для начала, создайте проект sfdemo, приложение app и модуль card: $ cd /home/steve $ mkdir sfdemo $ cd sfdemo $ symfony init-project sfdemo $ symfony init-app app $ symfony init-module app cart Настройте ваш веб-сервер, чтобы был доступ к вашему новому приложению (неважно как вы этого добьётесь используя виртуальный хост или alias’ы (в unix-like системах с помощью этой команды создается псевдоним какого-либо скрипта или приложения), как описано в главе настройки веб-сервера в документации). Давайте предположим, что модуль card доступен отсюда: http://localhost/cart/ Ваше приложение должно иметь доступ к symfony JavaScript библиотекам. Если приложение не работает, проверти доступ к библиотекам через браузер (зайдите на http://localhost/sf/js/prototype.js, например). Если страница не загрузилась, есть три способа решения этой проблемы:
настроить Apache используя следующий alias: Alias /sf /$data_dir/symfony/web/sf
сделать символическую ссылку sf в вашем веб-катологе $ cd /home/steve/sfdemo/web $ ln -sf /$data_dir/symfony/web/sf sf
скопировать JavaScript файлы в $ cd /home/steve/sfdemo/web $ mkdir -p sf/js $ cp /$data_dir/symfony/web/sf/js/*.js sf/js/
Главная страница Сначала нужно создать список продуктов, выставленных на продажу. Доступ к этому списку будет осуществляться через метод getProducts() action класса card. Корзина будет является полем объекта sfUser, устанавливаемый через Attribute parameter holder. Измените sfdemo/app/modules/cart/actions/actions.class.php на: class cartActions extends sfActions { public function executeIndex() { $this->getUser()->setAttribute(‘cart’, array()); $this->products = $this->getProducts(); } private function getProducts() { return array(‘iPod black’, ‘iMac’, ‘iMac RC’, ‘iPod’); } } Главная страница модуля card будет содержать список товаров и место, куда они будут перетаскиваться (drop zone). Это место и будет корзиной. Итак, откройте шаблон sfdemo/app/modules/cart/templates/indexSuccess.php и впишите туда следующие:
symfony Apple store demo
Products:
< ?php foreach($products as $id => $title): ?> < ?php echo image_tag(’product’.$id, array( ?id’ => ?product_’.$id, ?class’ => ?products’ )) ?> < ?php endforeach ?>
Cart:
Теперь товары будут отображаться в виде картинок. Эти картинки можно скачать в этом архиве, их следует положить в sfdemo/web/images/. Часть стилей уже сделаны, так что стоит их просто забрать отсюда, и положить в sfdemo/web/css/ также нужно добавить файл view.yml в sfdemo/app/modules/cart/config/ со следующим содержанием: all: stylesheets: [cart] (Обратитесь к документации, если вас смущают *.yml) Смотрим результат: http://localhost/cart/ Фокусируемся на корзине. Содержание корзины будет меняться, как только вы перенесете туда товар. Это значит что содержание корзины будет вынесено в отдельный файл шаблона. Для этого используем хелпер include_partial(). Товары в корзине будут «сохраняться» в div’ы со стилем float:left, а дальше после корзины нужно не забыть добавить стиль clear:both. (для тех, кто не понял зачем это смотрим спецификации) Измените конец шаблона indexSuccess.php на:
Cart:
< ?php include_partial(’cart’) ?>
Хелпер include_partial() заинклудит файл sfdemo/app/modules/cart/templates/_cart.php, который должен содержать следующее: < ?php foreach($sf_user->getAttribute(’cart’) as $product_id => $quantity): ?>
< ?php for($i = 1; $i <= $quantity; $i++): ?> < ?php echo image_tag(’product’.$product_id, array( ?class’ => ?cart-items’, ?id’ => ?item_’.$product_id.’_’.$i, ’style’ => ?position:relative’ )) ?> < ?php endfor ?> (< ?php echo $quantity ?> < ?php echo $products[$product_id] ?>)
< ?php endforeach ?> < ?php if (!$sf_user->getAttribute(’cart’)): ?> nothing yet in your shopping cart. < ?php endif ?> Если в корзине есть товар, то он отображается в виде картинок столько раз, сколько он туда добавлен. После группы товаров будет отображаться счетчик (переменная $quantity). Можно опять посмотреть на нашу корзину: http://localhost/cart/ На самом деле изменений не много, выглядит по-прежнему пусто… Настало время AJAX’a. (в оригинале «It’s time to make things AJAX».) Добавляем JavaScript’овые события. Добавьте в indexSuccess.php загрузку JavaScript хелпера: < ?php use_helper(’Javascript’) ?> Теперь нужно сделать картинки перетаскиваемыми (draggable), для этого нужно добавить вызов draggable_element: < ?php foreach($products as $id => $title): ?> < ?php echo image_tag(’product’.$id, array( ?id’ => ?product_’.$id, ?class’ => ?products’ )) ?> < ?php echo draggable_element(’product_’.$id, array(’revert’ => true)) ?> < ?php endforeach ?> Этим мы добавим ко всем картинкам возможность перетаскивания. Опция revert добавляет возврат картинки на старую позицию, как только ее отпустят. Теперь нужно определить, что будет происходить, как только пользователь бросит (перетащит) иконку товара в нашу корзину. Для этого укажем, какая часть шаблона должна обновится, какой action за это событие будет отвечать, и какие из перетаскиваемых элементов можно будет перетащить в корзину. Воспользуйтесь drop_receiving_elements хелпером для этого: < ?php echo drop_receiving_element(’cart’, array( ?update’ => ?items’, ?url’ => ?cart/add’, ?accept’ => ?products’, )) ?> Снова можно проверить результат, попробуйте перетащить иконку товара в корзину, должно работать. Как только иконка перетаскивается в корзину, XMLHTTPRequest отправляет запрос add action’у, и результат отображается в div’е items. Только дело в том, что action add модуля card мы еще не создали… Создаем action обновления. Добавьте add action в sfdemo/app/modules/cart/actions/actions.class.php: public function executeAdd() { $tmp = split(‘_’, $this->getRequestParameter(’id’, ”)); $product_id = $tmp[1]; $cart = $this->getUser()->getAttribute(’cart’); if (!isset($cart[$product_id])) { $cart[$product_id] = 1; } else { ++$cart[$product_id]; } $this->getUser()->setAttribute(’cart’, $cart); $this->products = $this->getProducts(); } Action разбирает присланные параметры (id товара) и добавляет этот товар в корзину. Результатом работы action’а add будет шаблон addSuccess.php. Здесь простой инклуд (используя include_partial) _cart.php, только в этот раз необходимо передавать список товаров в параметрах: < ?php include_partial(’cart’, array(’products’ => $products)) ?> Шаблон не должен использовать глобальное расположение, чтобы изменить это отредактируйте sfdemo/app/modules/cart/config/view.yml, вписав следующие: addSuccess: has_layout: off all: has_layout: on stylesheets: [cart] Посмотрите результат: теперь элементы должны добавляться в корзину без проблем. Фокусируемся на юзабилити. Можно остановиться на этом, но есть один большой недостаток: пока корзина обновляется, интерфейс не меняется и это может смутить пользователя. Выход из этой ситуации – добавление индикатора, который показывает, что запрос в процессе обработки. И еще, пользователь может не понять, что перетаскиваемые элементы будут приняты «корзиной», поэтому стоит добавить стиль hover к слою cart. Отредактируйте шаблон indexSuccess.php:
Сохраните картинку в файл sfdemo/web/images/indicator.gif Теперь, нужно изменить в этом же шаблоне вызов хелпера drop_receiving_element(): добавить отображение индикатора и hover стиль: < ?php echo drop_receiving_element(’cart’, array( ?update’ => ?items’, ?url’ => ?cart/add’, ?accept’ => ?products’, ’script’ => ?true’, ?hoverclass’ => ?cart-active’, ?loading’ => «Element.show(’indicator’)», ?complete’ => «Element.hide(’indicator’)» )) ?> Заключение. Полный код статьи можно скачать отсюда, также доступен рабочий пример он-лайн. Пока полная документация по JavaScript хелперу не дописана, можно воспользоваться документацией script.aculo.us. Оригинальная статья.