Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 151, АВГУСТ 2011 г.

Web-приложения с турбонаддувом: Фреймворк Kohana + шаблон проектирования MVC = love

Прошли те времена, когда было модно разрабатывать webприложения, состоящие из одного сценария, по уши напичканного кодом. На дворе 2011 год, и уже как-то несолидно придерживаться столь консервативных идей. Время двигаться вперед и отдавать предпочтение современным методам разработки — применению Content Management Framework. Сегодня я познакомлю тебя с одним из лучших представителей современных CMF.

Что такое фреймворк?

Content Management Framework (CMF) — набор инструментов для разработки систем управления контентом (Content Management System). В отличие от CMS, фреймворки (в большинстве случаев) не готовы к работе сразу, поскольку они представляют собой лишь отдельные кирпичики. Задача разработчика — набраться сил и сложить из этих материалов полноценное приложение. CMS — это тоже своего рода «кубики», но они готовы к работе из коробки и вполне могут функционировать без доработки кода.

Три главных плюса CMF

Если от фреймворков не было особой пользы, то никто бы не решился использовать их в своих проектах — жизнь современного разработчика и так достаточно тяжела. Из наиболее ощутимых плюсов CMF можно выделить:

  1. Оптимизированный код. Над фреймворками трудятся разработчики, уделяющие оптимизации достаточно много времени.
  2. Скажи «нет» велосипедам. Как правило, в фреймворке уже имеются готовые решения для типичных задач. Тут тебе и структура папок, и вспомогательные библиотеки, и куча всяких вкусностей. Многие вещи изначально готовы к работе и позволяют разработчику сразу приступить к разработке функционала приложения, не развлекаясь написанием кучи рутинного кода.
  3. Упрощенная командная работа. Если проект разрабатывается целой командой, то применение CMF (особенно популярного) дает ощутимый плюс при появлении в команде новенького. Ему будет проще включиться в проект, так как для этого необходимо ознакомиться с CMF, по которому наверняка написано множество статей и мануалов.

Святая троица: модель, представление, контроллер

Всех разработчиков условно можно разделить на две большие группы — «гангстеры» и «законопослушные граждане». Первые не придерживаются никаких стандартов и хорошо зарекомендовавших себя решений, а делают все наобум. Они не думают ни о каких шаблонах проектирования, а просто лепят код. В большинстве случаев такие программисты не способны заниматься большими проектами.

«Грабануть поезд» (в смысле, сорвать небольшой куш, написав простенькое приложение) — это всегда пожалуйста. Сделают быстро и без лишнего шума. А вот с крупными делами у них возникают проблемы. Для проектов, ТЗ которых содержит фразу «должен быть масштабируем», такие «специалисты» не годятся, поскольку наколбасить кучу кода в одном модуле и забыть в таких проектах не получится. Тут нужен определенный подход и максимальное разделение кода.

За годы развития языков программирования были созданы различные методики — паттерны («шаблоны») проектирования ПО. Одним из таких паттернов и является Model-View-Controller. Я бы даже сказал, что сегодня это, наверное, самый популярный шаблон.

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

Контроллер

Контроллер в MVC выполняет роль некоего диспетчерарегулировщика. Он не должен изменять или добавлять данные, производить расчеты и т.д. Его цель — обслуживать поступающие запросы и на каждый такой запрос соответствующим образом отвечать. Например, пользователь обращается к главной странице сайта нашего журнала — http://xakep.ru. Его запрос в первую очередь получает определенный контроллер (если рассматривать на примере шаблона MVC). После получения запроса он выполняет действие, забинденное на данный тип запроса. Причем сам контроллер ни в коем случае не должен содержать код для выборки данных и т.д. Сама выборка должна быть организована в модели.

Модель

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

Представление

Последний компонент архитектуры MVC — представление. Этот элемент отвечает за вывод данных в нужном виде. Именно во вьюшках (сленговое название представления) и должна быть вся разметка. Несомненно, в них также может содержаться и программный код, отвечающий сугубо за вывод данных, полученных от контроллера. Но никакой бизнес-логики там быть не может. Перспективы и плюсы использования MVC очевидны.

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

This is Kohana

Kohana — это бесплатный фреймворк с открытым исходным кодом. В качестве шаблона проектирования, как ты уже и догадался, в Kohana применяется паттерн — Model View Controller.

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

Ставим Kohana

Для начала прогуляйся до официального сайта и загрузи последнюю версию фреймворка. Загруженный архив закачай к себе на хост и извлеки его содержимое. Попробуй обратиться к директории своего хоста, в которую ты извлек фреймворк и… — приготовься к облому. Наверняка ты не пройдешь Environment Tests (тест окружения).

В моем случае тесты на запись в директорию хранения кэша и логов тоже завершились неудачей. Для исправления ситуации нужно всего лишь выставить права на запись для этих директорий. В общем, выставляй права и пробуй обновить страницу. В случае успеха увидишь текст: «Your environment passed all requirements. Remove or rename the install.php file now». Помимо радостного известия о готовности окружения для работы фреймворка, текст сообщения требует от тебя удаления файла install.php. Не будем брыкаться и выполним эту пустяковую просьбу. Удалив инсталляционный сценарий, попробуй обновить страницу. Если ты все сделал правильно, то браузер выплюнет девственно чистую страницу с текстом «hello, world».

Hello world на Kohana

Перед тем как перейти к рассмотрению полезного примерчика, попробуем наколбасить собственный «Hello world». Создадим новый текстовый файл и напишем в нем следующий текст:

<?php defi ned('SYSPATH') or die('No direct script access.');
class Controller_Test extends Controller {
public function action_index()
{
$this->response->body('Hello world! Hello, everyone!!!');
}
}

В этом клочке кода я описываю наш первый контроллер — класс Controller_Test, унаследованный от Controller. Обрати внимание на имя класса. В имени содержится Controller (обязательный префикс), а после него идет непосредственно название контроллера. Его мы пишем с большой буквы. В моем случае именем контроллера является Test. Контроллеры и модели должны храниться в директории App/ classes/controller и App/classes/model.

Создаем первую модель

Пробный контроллер у нас есть, теперь посмотрим, как описываются модели. Сначала рассмотрим вариант модели, которой не требуется взаимодействие с базой данных. Например, представим, что нам нужно определить модель myFirstModel:

class Model_myFirstModel extends Model
{
public function calcIt (a, b) {
return a + b;
}
}

В этой модели я объявил всего один метод — calcIt(). Он выполняет операцию сложения над переданными в качестве параметра переменными. Увы, если требуется работать с базой данных, то модель такого вида не прокатит. Все модели, предназначенные для взаимодействия с СУБД, должны наследоваться от Model_Database. Например, нам требуется написать модель, в которой предусмотрена возможность выборки данных из таблицы users. Такая модель будет выглядеть примерно так:

class Model_myFirstDBModel extends Database_Model
{
public function selectData() {
return $this -> db -> query('select userName,
pass from users');
}
}

Делаем первое представление

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

Все созданные представления должны храниться в папке views, расположенной в директории твоего приложения. По умолчанию директорией приложения является Application. Создавать представления чрезвычайно просто. Ради эксперимента попробуем создать представление about. Его код будет выглядеть примерно так:

<html>
<head>
<title><?php echo $title ?></title>
</head>

Я специально не стал приводить остальную часть кода, так как там может присутствовать абсолютно любой html-код. Нас интересует только то, что расположено между тегами <title>. Там я отправляю на «печать» значение одноименной переменной. Получается, что заголовок страницы будет устанавливаться извне — из контроллера.

Теперь посмотрим на обновленный код ранее рассмотренного нами контроллера:

$about_page = View::factory('about');
$about_page -> title = 'Это страница about';
$this -> response -> body ($about_page);

В первой строке я связываю переменную about_page с представлением about. Для этого я использую конструкцию View::factory. Далее я устанавливаю переменную title и вывожу само представление.

Хостинг изображений

Я долго думал насчет примера для сегодняшней статьи. Обычно при обзоре фреймворков пишут блог или другое типичное webприложение. Признаюсь честно, сначала я так и сделал — набросал блог с простой системой авторизации пользователей, админкой и т.д. Но потом подумал (вообще-то это я тебя насильственно переубедил :) — прим. ред.), что это скучно и решил сделать что-нибудь поинтересней. В итоге придумал рассмотреть такое приложение, как хостинг изображений. Таких проектов в инете пруд пруди, и несмотря на многообразие выбора, каждый имеет свою аудиторию.

Я понимаю, что для более-менее реального личного хостинга изображений нужно несколько гигабайт места. На обычном виртуальном хостинге получить их дороговато, а раз так, то и пользы от такого хостинга будет мало. И тут я подумал, а почему бы не заюзать в качестве хранилища отдельный аккаунт известного всем Dropbox? По умолчанию каждый акк позволяет хранить 2 гигабайта стаффа, но его без особых проблем реально прокачать до восьми. А вот восемь гиг вполне хватит для использования в личных целях. Немного покумекав и в очередной раз задержав статью, я набросал небольшой проект. Я не стал сильно извращаться, а реализовал лишь:

  • Удобную загрузку изображений. На большинстве опробованных мной хостингах изображений для отправки файлов требовалось выбрать нужный файл при помощи стандартного диалога открытия файлов. Это не очень удобно, тем более, возможности HTML5 легко и просто помогают реализовать Drag&Drop-интерфейс и считать файл с компа пользователя при помощи FileAPI.
  • Передачу файлов в DropBox. Для хранения файлов я выбрал предопределенную директорию public. Все хранящиеся в ней файлы могут быть расшарены для других пользователей. Dropbox автоматически генерит к ним ссылки. Именно эта ссылка и будет использоваться для передачи клиенту. Да, конечный адресок получается длинноватым, но при желании его можно укоротить. Сервисы для укорачивания ссылок тебе в помощь.

Внутренности проекта

Увы, привести полные листинги проекта в статье я не могу, поскольку кода (особенно оформления) достаточно много. Здесь я лишь поясню основные ключевые моменты. Итак, начнем разбор с контроллеров. Для проекта мне потребовался один контроллер, одно представление и одна модель. В контроллере я объявил два методасобытия. Первое возникает, когда пользователь обращается к основной странице, а второе — в случае успешной загрузки изображения на сервер (генерируется страница со ссылкой на файл).

Первое представление — самое простое. По факту, это — страница с небольшим полем, на которое нужно перетаскивать файлы. Код страницы прост до безобразия:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Демонстрация работы CMF Kohana для ][акера</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="html5uploader.js"></script>
</head>
<body onload="new uploader('drop', 'status', 'uploader.php',
'list');">
<div id="box">
<div id="status">Перетащи на меня файл</div>
<div id="drop"></div>
</div>
<div id="list"></div>
</body>
</html>

В коде я определяю простенькую разметку и подключаю готовую библиотеку html5uploader. В этой JS-библиотеке уже реализовано все необходимое для создания красивой html5-страницы для передачи файлов на сервер. Для передачи файла достаточно забиндить на событие onload создание экземпляра объекта uploader. В конструктор объекта необходимо передать следующие параметры:

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

Последний параметр можно не заполнять. Обрати внимание, к данному html-файлу я прилинковал style.css. В нем содержится описание стилей. Если ты попытаешься повторить пример, то обязательно копирни css-файл, иначе твоя страница так и останется девственно чистой.

Теперь посмотрим, как работать с Dropbox. Как всегда есть два варианта. Первый — гиковский. Думаю, ты уже догадался, что придется все писать самостоятельно. Второй проще и правильней — воспользоваться готовым модулем. Пока таких модулей не очень много. Для себя я выбрал самый простенький, который так и называется — DropboxUploader. Ссылку на его загрузку ты найдешь в конце статьи.

Модуль представляет собой класс с одним полезным методом — upload. Передача файлов в аккаунт DropBox’а выполняется следующим образом:

$uploader = new DropboxUploader('твой_логин', 'твой_пароль');
$uploader->upload('файл для загрузки', 'папка назначения');

Поскольку я решил загружать все файлы в папку public, то в качестве второго параметра мне требуется передать — /pupblic. Если необходимо загружать файлы прямо в корень аккаунта, то указывай просто слэш — '/'.

Код приемки файла на стороне сервера выглядит следующим образом:

if(count($_FILES)>0)
{
$uploader = new DropboxUploader('login', 'pass');
$uploader->upload(
$upload_folder.'/'.$_FILES['upload']['name'],
$dropbox_folder);
if(move_uploaded_fi le($_FILES['upload']['tmp_name'],
$upload_folder.'/'.$_FILES['upload']['name'] ) )
{
echo 'done';
$uploader = new DropboxUploader('login', 'pass');
$uploader->upload(
$upload_folder.'/'.$_FILES['upload']['name'],
$dropbox_folder);
}
exit();
}
...

Здесь я привел код считывания файла с использованием глобального массива $_FILES. С ним очень удобно и просто работать, но стоит помнить об одном маленьком условии — браузер клиента обязан поддерживать метод передачи файлов — sendAsBinary(). В противном случае тебе придется самостоятельно декодировать полученные данные из base64 (если они были закодированы именно этим алгоритмом). Я реализовал оба варианта. Второй ты можешь посмотреть в моем исходнике.

Заключение

Фреймворки существенно облегчают процесс разработки webприложений и прививают разработчику «культуру разработки», помогают писать более красивый и правильный код. Рассмотренная Kohana обладает весьма привлекательными возможностями и уже из коробки содержит готовые решения для типичных задач. Попробуй начать использовать Kohana в реальных проектах. Уверен, ты прочувствуешь ее мощь и гибкость и уже не захочешь возвращаться на голый php. На этом кланяюсь и желаю тебе удачи. Как обычно, все свои вопросы можешь кидать на мыло.

Что почитать

  • http://goo.gl/sRjoo — моя большая статья про CodeIgniter. Kohana берет свое начало именно с этого проекта. Несмотря на крутизну Kohana, иногда не грех воспользоваться и CodeIgniter’ом. К тому же, разработчики вроде бы опять возобновили разработку.
  • http://kohanaframework.org/ — официальный сайт проекта Kohana. Здесь ты найдешь сам фреймворк, а также всевозможную документацию и примеры использования. После прочтения статьи рекомендую сразу посетить этот ресурс.
  • http://vr-online.ru — всегда свежие статьи по программированию. В плане CMF, ресурс может похвастаться наличием статей по CodeIgniter, Drupal и т.д.
  • http://kerkness.ca/wiki/doku.php — хорошая неофициальная документация по Kohana.
Содержание
ttfb: 7.3468685150146 ms