Как стать автором
Обновить

PHP — фреймворк с поддержкой плагинов за 5 минут

Время на прочтение5 мин
Количество просмотров1.9K
Многие из нас сталкивались с проблемой поиска удобного многофункционального фреймворка на PHP, скором в изучении и минимальным размером кода. В свое время я тоже озаботился этим вопросом и с интересом изучал сравнение и отзывы о различных фреймворках, некоторые даже скачал и бегло просмотрел исходный код (такая уж привычка). В силу своей лени и ограничения во времени, курить маны какого-то нового движка было откровенно неохота. Как известно, лень – двигатель прогресса, было принято волевое решение написать коротенький фреймворк с необходимой для меня функциональностью. Итак, задача поставлена, бутылка пива откупорена, и под девизом «меньше поросят, меньше визга» я приступил. Что получилось смотрите сами:

/* определение объекта действия и задачи */
if (preg_match('/^(.+?)_(.+)$/', $action, $matches)) {
    $object = $matches[1];
    $task   = $matches[2];
} else {
    $object = $task = null;
}

/* нужен ПРЕпроцессор? */
if (($task == 'add' || $task == 'update') && file_exists("../inc/$object.pre.php"))
    require "$object.pre.php";

/* подготовка данных для шаблона */
if (file_exists("../inc/$object.inc.php"))
    require "$object.inc.php";

/* отрисовка шаблон->HTML (Dwoo) */
$tpl->output('main.tpl', $td);




Более наглядно:
Scheme

Вот и все, в приниципе, фреймворк готов. Все просто, разобраться легко. Размер кода – минимум, фукнциональность – чудовищная (неочевидно? читаем дальше).

Было решено что в качестве основного параметра, на который будет реагировать диспетчер плагинов фреймворка, будет выступать переменная $action, которая будет содержать в себе ОБЪЕКТ ($object) и ДЕЙСТВИЕ ($task), и иметь строковый вид «объект_действие». Например, «service_edit», «article_new», «customer_update». Соответственно, URI может быть такой: "/service_edit/123", "/article_new", "/customer_update/10077". Как URI разделить на переменные и присвоить им соответствующие данные – на ваше усмотрение (я использую апачевский rewrite).
Допустим, мы получили переменную $action=«customer_update», она режется при помощи preg_match на $object=”customer” и $task=”update”, в случае неверного формата $action, переменные $object и $task очищаются (впоследствие для вывода сообщения об ошибке).

Плагины находятся не в корне html, а в “../inc” (расположение их до корневой директории способствует секурности), вообше, считаю что в корне должно быть css/,js/,img/,index.php и, при необходимости, пару служебных *.php (для AJAX и т.п.).

Наименование файлов плагина такое: <объект>.pre.php и <объект>.inc.php. Наличие этих файлов в соответствующем каталоге автоматически превратит их в плагины, вызываемые в зависимости от $object.

PRE в названии файла – это препроцессор, может включать в себя
  • валидацию данных из формы
  • изменение БД – INSERT/UPDATE в SQL
  • изменение $object для смены схемы отображения

Важно для понимания – если после отработки препроцессора нет надобности менять страницу на стороне клиента, то скрипт можно закончить выдачей результатов в json (ajax) и выйти по exit; управление далее не передается, а именно <объект>.inc.php НЕ вызывается.
Навскидку, в каких случаях это может быть:
– некорректный ввод данных в форме – нет надобности перерисовывать всю страницу с формой (заполняя ее только что введенными данными – они и так уже есть на экране), нужно лишь указать об ошибке подсветив ошибочное поле и/или вывести попап с указанием ошибки (используется технология ajax+json)
– данные успешно введены, но по алгоритму менять страницу на клиенте не надо, форма должна остаться на экране после подтверждения ввода (смысл ее убирать с экрана и тут же перерисовывать снова с теми же данными?).
Если технология ajax вами не используется и/или нужно перерисовать страницу целиком на стороне клиента, то просто меняем $object/$task (а возможно и $action) на те, которые необходимы для диспетчера и вызова <объект>.inc.php для отрисовки новой страницы. Например:
– после добавления абонента перейти к списку абонентов (меняем $action “customer_add” -> “customer_list”)
– после изменения сервиса перейти к списку сервисов (меняем $action “service_update” -> “service_list”)
– после какого либо действия, но по факту истечения срока сессии перейти к форме логина (меняем $action на ”system_exit”)
– если $action == ”admin_login”, и есть несовпадения некоторых секурных параметров можно $action заменить на “customer_login” :) (для этого, разумеется, надо изменить проверку необходимости вызова PRE в if)
Таким образом, манипулируя значением переменных $object/$task,$action мы можем менять вызов плагина отображения <объект>.inc.php.

INC в названии файла – это часть плагина отвечающего за подготовку данных для генерации HTML страницы. Важно для понимания – код HTML НЕ ГЕНЕРИРУЕТСЯ при помощи php в плагине, никаких echo или print в нем нет (и, надеюсь, не будет).

Небольшое отступление: генерация HTML кода из php… Вообще, просматривая примеры из жизни я встречал разного рода заблуждения, например (популярная вебморда):
wierd code
Когда я вижу php код (написанный руками!) где HTML страница генерируется при помощи echo или print, иными словами, где бизнес-логика не отделена от логики представления, мне становится дурно. Бывает, генерация страница от <html> до </html> разнесена на несколько скриптов (классов) длиной в сотни строк, дебажить нереально. Чего скрывать, еще будучи младенцем пяток лет назад я и сам страдал этим психозом, писал универсальные функции, генерирующие код HTML в зависимости от переданных параметров, пока у меня не открылись глаза (спасибо, Nick) на то, что в мире изобрели шаблонизаторы. Вселенское счастье свалилось на меня, когда я увидел шаблонизатор Smarty. Как я жил без него раньше, ума не приложу….

Ну да я немного отвлекся, простите. Итак что там у нас… а, ну да, часть плагина, которая INC, готовит данные для последующей генерации страницы, делаются выборки из SQL, структурируются данные, вообщем, готовим некий массив, который облагородит своими данными шаблонизатор, который в свою очередь выстрелит нам чистый код HTML. Это делается командой:

$tpl->output('main.tpl', $td);

Это вызов метода шаблонизатора, который превратит данные из массива $td при помощи шаблона main.tpl в HTML страницу, которую заказывал клиент.
Естественный вопрос у вас может возникнуть на этом этапе – Как же так, столько объектов и действий, а вызывается всего один шаблон, он что, весит мегабайт? – А вот и не угадали, разумеется это уже из области логики отображения — это диспетчер шаблонов. Вот как он выглядит:
<!DOCTYPE …….>
<html>
<head>
      Всякая муть с подключением CSS, Javascript…
</head>
<body>
{if isset($template)}
    {include($template)}
{else}
    Incorrect action.
{/if}
</body>
</html>


В реале около 4 КБ. Разумеется, общая часть в виде заголовков не должна дублироваться в шаблонах (если надо, можно и тут кастомизировать). Сущность у всех разная, соответственно подключается шаблон, который вы укажете. Соответствующий файл <объект>.tpl должен присутствовать в каталоге, где хранятся шаблоны (например, ../tpl).
Долгое время в качестве шаблонизатора я использовал Smarty, однако, в последнее время отдаю предпочтение Dwoo. Это тоже самое что и Smarty, только быстрее и удобнее в синтаксисе. Шаблонизаторы и как правильно с ними работать обсудим в моем следующем посте, если на то будет воля хабрасообщества :)

Уф, вроде бы идею изложил, пока без деталей (подключение к SQL, заточенный под фреймворк ajax+json в шаблонах, детали создания плагинов и пр.). Надеюсь устранить этот недостаток в следующих частях.

Подведем итоги:
Кому счастье от этого фреймворка? – Прежде всего разработчикам, каждый занимается своим плагином, не мешая другому, не нужно стареть изучая структуры классов и методов. Вебдизайнеру – делает шаблон (который выглядит как обычный HTML) не трогая кодера php.

Область применения данного фреймворка довольно велика. На его базе я написал пару биллинговых систем для интернет-провайдеров (одна полностью на AJAX с динамическим div, другая наполовину — c iframe), систему складского учета.

Похвалите/поругайте :)

PS Если интересно, опишу детали.
Теги:
Хабы:
Всего голосов 44: ↑20 и ↓24-4
Комментарии93

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань