LXF95:Akelos
|
|
|
Ruby on Rails взял штурмом мир программистов, вызвав у тех из нас, кто все еще пишет на PHP, жуткую зависть к такому элегантному методу работы. Если вы еще не видели пятнадцати минутный ролик Look at what I’m not doing («Смотри, чего я НЕ делаю»)на www.rubyonrails.org – посмотрите непременно: он запросто сагитирует вас плюнуть на PHP и перейти на Ruby.
Вся магия Rails – в метапрограммировании. Немалая часть кода создается за вас, так что вам не приходится всякий раз вспоминать, где какой класс находится и куда поместить такую-сякую функцию. Это сильно упрощает работу в рамках архитектуры: обучение ускоряется, и надо меньше задумываться в процессе работы. Таков Rails; но ведь у сообщества PHP естб и собственные системы разработки. У каждой из них свои сильные и слаюые стороны, и Akelos – это Rails для PHP, нас колько такое только возможно. Большая часть элементов архитектуры сохранилась. за исключением тех моментов, которые на PHP лучше сделать иначе. Akelos написан так, что совместим и с PHP 4, и c PHP 5, так что его можно установить практически на любом сервере. Это было одним из важных аргументов в пользу Akelos в нашей компании, так как, хотя мы стараемся в основном использовать PHP 5, иногда нам приходится разрабатывать приложения для работы на старом оборудовании или же для клиентов, которые просто не хотят обновлений.
Все это делает Akelos идеальным для быстрого развертывания приложений, которые должны работать где угодно. На нашем уроке мы рассмотрим его и создадим простенькое web-приложение, чтобы вы поняли, как использовать каркас на полную катушку. В итоге вы получите полноценную рабочую программу, но учтите, что на серьезное рассмотрение у нас здесь места мало – мы только пройдемся по верхам. Советую самостоятельно зарыться в код и разобраться, на что он еще способен!
Содержание |
Чего вы не делаете
Благодаря метапрограммированию, вы можете изучить Akelos очень быстро, потому что он очень многое сделает за вас. При изучении других сред программирования вам нужно было помнить, где расположить классы каких типов, какие функции какие классы реализуют, и как применять объекты каждого из типов. На Akelos вам не нужно изучать, что такое контроллер и куда его засунуть: вы можете предоставить его генерирование программе. Она умеет создавать целые семейства классов и файлов при помощи команды scaffold.
Давайте установим Akelos и попробуем в деле. Вам понадобится сервер Apache с MySQL, SQLite или PostgreSQL. Возьмите Akelos с www.akelos.org или из каталога Magazine/Akelos на приложенном диске. Распакуйте файл в каталог (он будет называться akelos_framework), расположенный внутри корневого каталога web-сервера. В целях нашего урока назовем этот каталог akelos, так что теперь вы можете открыть его в браузере по адресу http://localhost/akelos. Выполните инструкции, чтобы завершить установку. Вам понадобится сервер Apache с MySQL, SQLight или PostgereSQL. Возьмите Akelos с www.akelos.org или из каталога Magazine/Akelos на приложеном диске. Распакуйте файл в каталог (он будет называется akelos_framework), расположенный внутри корневого каталога web-сервера. В целях нашего урока назавём этот каталог akelos, так что теперь вы можете открыть его в браузере по адресу http://localhost/akelos.
Выполните инструкции, чтобы завершить установку. Вам понадобится настроить 3 базы данных – одну для разработки, одну для эксплуатации и одну для тестирования. Для тонкой настройки вам может потребоваться изменить первую строчку файла /scripts/generate и некоторых сценариев так, чтобы она указывала на исполняемый файл PHP для работы в коммандной строке:
'#!/usr/bin/env php'
В дальнейшем я предполагаю, что вы установили в систему каталог с названием akelos, так что URL для доступа к нему должен быть http://localhost/akelos/public. Если у вас возникли сложности с просмотром примеров в браузере – проверьте, как начинается правило RewrriteBase в файле public/.htaccess – оно должно содержатьь путь к каталогу public.
Итак, мы можем начинать. С помощью вашей любимой оболочки для 3ev. командной строки перейдите в каталог с распакованным приложением и выполните команду generate:
cd /path/to/untarred/akelos/ scripts/generate
Вы увидите некоторое описание, что делает generate и как ее использовать. На следующей странице, во врезке «Сценарии» вы найдете список команд, которые она умеет выполнять. Пока запустите
./scripts/generate scaffold Post
а затем откройте в браузере адрес 'http://localhost/akelos/public/post' (не забудьте изменить адрес, если вы установили Akelos в какую-то другую директорию). Вы увидите экран со ссылкой для создания нового Post’а, довольно пустынный, однако кнопка Create New Post там есть. Кликните на нее и введите какие-нибудь данные. После сохранения записи вы сможете увидеть ее на 'http://localhost/akelos/public/' post, а также сможете изменить или удалить ее, пользуясь соответствующими ссылками.
Команда scaffold генерирует для вас приложение, уже имеющее базовый набор функций, ожидаемый от web-приложения: создание, редактирование и удаление записи в базе данных из браузера. В этом вся прелесть метапрограммирования – большую часть работы делать не надо!
Но что все-таки произошло? А вот что: генератор кода создал для вас каркас приложения, включающий контроллер, помощник и несколько видов. В нашем случае он так же создал простой класс model, состоящий из названия и описания, что и позволило вам заполнять эти поля. Одной командой – generate scaffold – вы выполнили основную часть работы по написанию приложения для создания и редактирования записей базы данных.
Взгляд на вид
Вид – это такая штука, которую видит пользователь. Это буквально и есть внешний вид программы. Все виды вашего приложения должны располагаться в папке app/views. Когда вы открываете страницу приложения Akelos, соответствующий вид определяет, как она выглядит. Например, при открытии http://localhost/akelos/public/post/listing вызывается шаблон views/post/listing.tpl. Когда вы щелкнете на какойнибудь элемент списка, в работу вступит view.tpl.
Откроем /views/post/listing.tpl и рассмотрим его содержимое. Вы увидите, что шаблоны в основном состоят из HTML и PHP, однако в дополнение к ним используется набор специальных тэгов [sintag], позволяющих избежать повторов в коде. Систему тэгов разработала та же команда, которая написала Akelos. Для выделения тэгов они использовали фигурные скобки – { и }.
В файле listing.tpl можно найти следующий участок кода:
{loop posts} <tr {?posts_odd_position}class=”odd”{end}> {loop content_columns} <td class=”field”><?php echo $post->get($content_column)?> {end} …
Первая строка начинает цикл по списку объектов Post, а четвертая строчка выводит значение очередного свойства текущего объекта. Попробуйте заменить текст от {loop content_columns} до {end} двумя строчками ниже на
<td class=”field”>{post.name} <td class=”field”>{post.description} <td class=”field”>{post.created_at} <td class=”field”>{post.updated_at}
Все, что мы изменили – это сделали индивидуальную обработку каждого из полей и добавили жирный шрифт для имени записи, однако это неплохая иллюстрация использования спецтэгов. Чтобы понять, зачем они нужны для некоторых задач в PHP, откройте файл views/ post/compiled/listing.tpl.php. Посмотрите, на что был заменен одинединственный тэг {look posts}:
<?php empty($posts) ? null : $post_loop_counter = 0; empty($posts) ? null : $posts_available = count($posts); if(!empty($posts)) foreach ($posts as $post_loop_key=>$post){ $post_loop_counter++; $post_is_first = $post_loop_counter === 1; $post_is_last = $post_loop_counter === $posts_available; $post_odd_position = $post_loop_counter%2; ?>
На этом можно пальцы вывихнуть! Если вам придет охота самим организовать цикл на PHP, ничто не мешает это сделать, но система спецтэгов экономит время.
Как насчет дизайна приложения? Главная HTML-страница вашего приложения – app/views/layout/post.tpl, а таблица стилей по умолчанию для каркаса Akelos – public/stylesheets/scaffold.css. Файл CSS подключается к шаблонам строкой
<?php echo $asset_tag_helper->stylesheet_link_tag(‘scaffold’) ?>
Можно редактировать файл scaffold.css напрямую, но почему бы не разработать для вашей программы свой собственный стиль? Создайте файл /public/stylesheets/myapp.css и внесите в него следующие определения:
h1 { border-bottom : thin solid black; padding : 3px; }
Осталось добавить в заголовок HTML файла views/layout/post.tpl следующую строчку:
<?php echo $asset_tag_helper->stylesheet_link_tag(‘myapp’) ?>
Конечно, вы можете как использовать один и тот же CSS-файл для всех контроллеров приложения, так и определять для каждого из них свой собственный файл и внешний вид.
Контролируем контроллер
Теперь рассмотрим контроллеры. Они определяют, что пользователь увидит и когда, а также соответствие URL-адреса и действия, которое можно выполнить по этому адресу. Когда вы посещаете book/edit/123/, Akelos определяет, какой контроллер вы хотите использовать, какая операция контроллера была вызвана и к какой записи его нужно применить. В этом примере контроллером будет book, операцией – edit, а номер записи 123.
Откроем app/controller/post_controller.php и пробежимся взглядом по его структуре:
class PostController extends ApplicationController
{ // Index is the default action function index() { /* нечто... */ } // the listing function function listing() { /* нечто... */ } function show() { /* нечто... */ } function edit() { /* нечто... */ } ... }
Каждая функция контроллера соответствует некому действию, которое может предпринять пользователь – получить список записей, просмотреть их или отредактировать. Сгенерированный нами каркас имеет набор основных операций, свойственных web-приложению, но вы можете добавить к контроллеру все что угодно. Для этого сначала добавляется функция:
function hello() { // вам совершенно не обязательно что-то тут писать }
После создания функции нужно добавить TPL-файл с тем же именем в каталог app/views/post/, так что создадим app/views/post/hello.tpl и поместим в него следующую строчку:
<Н1>Hello, World!</Н1>
А теперь зайдите на http://localhost/akelos/public/post/hello. Возможно, именно с этого нам бы и следовало начинать, однако с Akelos «Hello World» написать сложнее, чем полноценное web-приложение!
Функции контроллера могут выводить текст напрямую, без использования шаблонов – через функцию render(). Разовьем нашу функцию и обновим страницу в браузере:
function hello() $this->render( array ‘text’ => ‘Hello, World - from inside the controller’ ) ); }
Этот вызов игнорирует шаблон, выводя данные прямо из контроллера, и его можно использовать для функций Ajax, как мы увидим в дальнейшем.
Наконец, операции контроллера можно перенаправлять на другие операции. Изменим функцию hello() еще раз:
function hello() { this->renderAction(‘listing’); }
Теперь, когда вы зайдете на public/post/hello, вас перенаправят на страницу со списком записей, точно так же, как это происходит при обработке операции index(). Если вы хотите узнать, на что еще способен контроллер, обратите внимание на функции класса lib/AkActionController.php.
Про инсталляторы
Вместе с Akelos вы получаете мощный инструмент управления таблицами баз данных, включая поддержку изменений и обновлений структуры. Это может сэкономить вам часы возни с SQL-кодом и значительно упростить процесс разворачивания и обновления вашей программы. Команда generate scaffold, которую мы использовали раньше, создала в том числе и файл инсталлятора app/installers/post_installer.php. Откроем его и посмотрим:
function up_1() { $this->createTable(‘posts’, “ id, name, description, created_at, updated_at “); } function down_1() { $this->dropTable(‘posts’); }
Инсталлятор создает таблицу под названием posts c полями id, name, description, created_at и updated_on. Команда generate scaffold тоже создает таблицу автоматически, но вы можете пересоздать ее вручную:
./scripts/migrate Post uninstall
(эта команда вызывает down_1(), при этом удаляя таблицу), и вернуть ее обратно с помощью
./scripts/migrate Post install
(вызов up_1() создаст таблицу заново).
Если после этого вы зайдете на http://localhost/akelos/public/post, то увидите, что все записи исчезли, а таблица была пересоздана.
Как вы поняли, функция up_1() используется для установки, а down_1() – для деинсталляции. Точнее будет сказать, что up_1() используется для увеличения номера версии, а down_1() – для уменьшения. Чтобы разобраться в этом, создадим новую функцию инсталлятора с названием up_2():
function up_2() { $this->addColumn(‘posts’, ‘extracol’); }
Запустите команду install снова и посмотрите, как теперь выглядит таблица в базе данных, с помощью клиента MySQL. Видно, что инсталлятор выполнил команду ALTER TABLE posts ADD extracol, добавив в таблицу новый столбец.
Соответствующие функции down_ служат для отката изменений, так что давайте создадим down_2(), действие которой обратно действию up_2():
function down_2() { $this->removeColumn(‘posts’, ‘extracol’); }
Теперь запустите uninstall, и увидите, что были запущены две SQL-команды:
SQL ALTER TABLE posts DROP COLUMN extracol ... DROP TABLE posts
Эти команды соответствуют вызовам down_2() и down_1(). Функции отката должны точно соответствовать функциям установка, чтобы при установке от откате не было никаких ошибок.
Функции createTable(), dropTable и removeColumn() – это просто оболочки для библиотеки доступа к данным AdoDB, которую Akelos использует при всех операциях с базой данных. У Akelos есть еще несколько полезных функций, таких как changeColumn(), renameColumn(), addIndex() и removeIndex(). Если вам нужен прямо доступ к объекту AdoDB из инсталлятора, используйте $this->data_dictionary.
Полезно обдумать, какие изменения вносит инсталлятор в процесс разработки и установки приложения. Работающие в группе должны знать, как сложно бывает выкрутиться, когда вносимые в структуру данных изменения конфликтуют между собой – на разрешение таких конфликтов тратится куча времени и нервов. Используя функции повышения и понижения версии базы данных, разработчики могут легко менять структуру и не беспокоиться о конфликтах. Если же конфликт все-таки возникает, достаточно бывает слить две PHP-функции в одну или же написать функцию up_() заново с учетом конфликтных требований.
Маленькие помощники Akelos
А теперь поиграем с помощниками, предоставляющими полезные функции, не являющиеся частью модели, вида или контроллера. К ним относятся задачи генерации URL, обработки текста, создания простых меню и построения HTML-тэгов. Вместе с Akelos поставляется целая куча помощников, каждый из которых отвечает за свой тип функциональности. Например, url_helper содержит функции построения URL (например, составление ссылки на какое-то действие определенного контроллера):
<?= $url_helper->link_to(‘Go to the help page’, array(‘action’ => ‘help’) );
?>
Второй ценный помощник – menu_helper. Он умеет генерировать меню возможных операций контроллера, например
<?= $menu_helper->menu_for_controllers(array(‘post’=>array(‘help’, ‘list’))) ?>
Понравилось? Перечисляя интересных помощников, нельзя не упомянуть про form_helper и date_helper. Очень полезно изучить их возможности (да и остальных тоже), для этого можно заглянуть в lib/AkActionView/helpers/.
В добавление к помощникам, содержащим основные функции для использования во всех приложениях, при каждой генерации каркаса создается свой собственный помощник. Например, при создании каркаса Foobar будет сгенерирован foobar_helper, а чтобы вызвать его из кода приложения, можно воспользоваться переменной $foobar_helper. Вернемся к нашему приложению: откройте файл app/helpers/post_ helper.php и добавьте в него функцию
function quick_destroy(& $record) { return $this->_controller->url_helper->button_to(‘Delete in 1 click’, array(‘action’ => ‘quick_destroy’, ‘id’ => $record->getId()), array( ‘confirm’ => ‘Are you sure?’ )); }
А затем в файл app/views/post/listing.tpl впишите строчку
<td class=”operation”><?php echo $post_helper->quick_ destroy($post)?>
Осталось только добавить в контроллер следующую функцию:
function quick_destroy() { if(!empty($this->params[‘id’])){
$this->post = $this->Post->find($this->params[‘id’]);
$this->post->destroy(); $this->redirectTo(array(‘action’ => ‘listing’));
}
}
Обновите страницу со списком записей – и увидите новый столбец Delete in 1 click. При щелчке по любой записи в этом столбце, JavaScript выдаст окно с вопросом, уверены ли вы, а после ответа «Да» запись будет удалена без всяких проволочек.
Ajax, но без JavaScript
Технология Ajax позволяет загружать фрагменты HTML на страницу после ее отображения и обрабатывать формы и команды, не перезагружая заново всю страницу целиком. Это стало очень популярным, поскольку так проще и пользователям, и разработчикам. Rails сделал Ajax еще более популярным, так как скрывает большую часть кода на JavaScript. И, как вы можете ожидать, Akelos умеет делать то же самое. Начнем с добавления следующей строки в HTML-заголовок файла app/ views/layouts/post.tpl:
<?= echo $asset_tag_helper->stylesheet_link_tag(‘prototype’) ?>
Помощник asset_tag_helper используется для подключения
JavaScript, CSS и других внешних файлов, и добавит любой JavaScript из каталога public/javascripts/ таким же образом.
Затем создадим операцию контроллера ademo (см. раздел «Контролируем приложение» на стр. XX, если вы забыли, как это делается). Кроме того, нам понадобится файл app/views/post/ademo.tpl:
<Н1>Quick AJAX example</Н1>
<?= $prototype_helper->link_to_remote(‘>Load the listing – by AJAX!’, array(‘url’ => array(‘action’ => ‘getme’), ‘update’ => ‘updateme’ ) ); ?>
Ну и, наконец, создадим функцию контроллера с названием getme:
function getme() {
$this->render( array( ‘text’ => ‘Whooa! How easy was that?’ ) ); }
Откройте в браузере http://localhost/akelos/public/post/ajax, щелкните на ссылку, и вы увидите маленький текстовый блок, загруженный на страницу без перезагрузки. Таким же способом можно загрузить на страницу все что угодно – другие страницы, формы, картинки – и вам не придется даже задумываться о JavaScript, потому что за него отвечают функции помощника.
Если вы никогда не имели дела с Ajax, система наподобие Akelos – не самый лучший способ изучить его, потому что он скрывает от вас много тонких деталей. Однако вы можете оценить, насколько быстрее делать вещи именно таким способом.
Будущее Akelos
Мы приближаемся к завершению нашего краткого обзора каркаса, который сторицей отплатит за время, затраченное на его изучение. Мы даже не успели рассмотреть такие вещи, как обработка взаимосвязей в базе данных, но вы уже могли понять силу метапрограммирования и чистоту архитектуры – наследие Rails.
В моей фирме Akelos используется уже давно, и мы нашли, что он очень удобен для прототипирования, да еще и позволяет в ноль секунд создавать приложения. Благодаря совместимости с PHP4 и PHP5 он просто идеален в том случае, когда заранее неизвестно, в какой среде придется работать программе.
В данный момент существует небольшое, но активно растущее сообщество посвященное Akelos, и Берми Феррер [Bermi Ferrer], ведущий программист, планирует поработать над документацией и перезапустить web-сайт. LXF