- PVSM.RU - https://www.pvsm.ru -

Aleph PHP Framework

Итак, встречайте Aleph!

Новый микро-фрэймворк на PHP, по размеру и функционалу, которого уместно сравнение разве что только с медицинским скальпелем.

По умолчанию содержит всё необходимое для быстрого старта и написания приложений.

Причины, почему стоит обратить на него внимание:

  • Фрэймворк реально маленький. Обильно сдобренный phpDoc комментариями код занимает около 3000 строк;
  • Фреймворк является результатом более чем 6-ти летней профессиональной деятельности его авторов в области web-разработок;
  • Возможности фрэймворка позволяют использовать его как базу под практически любое приложение.

Причём Aleph — это пока что только ядро полноценного фреймворка, уже готового и давно используемого в реальных web-приложениях. Публикация остальных частей системы не за горами — вы просто влюбитесь в возможность проектировать и реализовывать приложения так, как если бы вы делали это в десктопном программировании (не надо пытаться представить это прям сейчас и тут же критиковать, дождитесь пока не увидите это своими глазами, и поймёте, что я имел в виду). Есть и ORM, и система контролов (именно контролов, типа тех, что в ASP.Net), валидаторы, кэширование, шаблонизация и всё то, что делает набор вспомогательных библиотек фреймворком.

Ядро написано на php 5.3.0 и код использует возможности языка, появившиеся в этой версии. Код распространяется по лицензии MIT, ссылки на гитхаб и сайт с документацией и форумом — в конце статьи кода немного, всё прокомментировано, пояснения по структуре есть на сайте.

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

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

Aleph PHP Framework

В корне проекта видим следующее — файл index.php, что является единой точкой входа в приложение (уверен, не мне вам рассказывать о содержимом лежащего рядом .htaccess), папка lib, в которой лежит собственно само ядро (файл aleph.php) и специальный скрипт requirements.php, результаты запуска которого подскажут вам, готова ли ваша система для запуска приложений на базе Aleph. В корне также лежит файл 404.html в качестве примера шаблона страницы ошибки.

Aleph PHP Framework

Но самое интересное для нас, конечно же, содержимое папки app. Без лишних деталей: папка cache — для хранения специальных файлов кэша при выборе в конфигурации кэширования на файлах (идёт вместе с ядром), и папка logs для служебных файлов логирования системной информации. Никаких жёстких ограничений (как и вообще ограничений во фреймворке) на расположение и название этих папок не накладывается (всё это запросто конфигурируется).

В папке engine лежат уже непосредственно файлы нашего приложения.

В качестве демонстрации был выбран не магазин, не блог и даже не todolist. Потому что когда смотришь реализацию блога на %framework_name% или реализацию магазина на %another_framework_name% невольно начинаешь задумываться «это хорошо, в рамках поставленной задачи фреймворк ведёт себя отлично, но как на нём сделать то, что мне нужно?». Aleph не отвечает на эти вопросы, он даёт вам отличный инструмент для адаптации к тому, что вам нужно. Помните, про парня, которому нужен был молоток? (Из статьи http://habrahabr.ru/post/141477/ [1]). Так вот, в php всё ещё пользуются молотками, и это имеет практический смысл, если вы понимаете, о чём я.

Впервую очередь продемонстрируем возможности роутинга в ядре. Все мы прекрасно знаем, что регулярные выражения в умелых руках — классная штука, этим роутинг и пользуется. Взглянем на содержимое файла index.php:

<?php

// на случай выполнения скрипта в шелле
$_SERVER['DOCUMENT_ROOT'] = __DIR__;

// единственный инклуд для файла ядра
require_once('lib/aleph.php');      

// инициализация ядра файлом конфигурации
$a = AlephCoreAleph::init()->config('app/engine/config.ini');

// удаляем из файлового кэша "просроченные" данные
if (method_exists($a->cache(), 'gc') && isset($a['cache']['gcProbability']))
{
  if ((int)$a['cache']['gcProbability'] > rand(0, 99)) $a->cache()->gc();
}

// непосредственно роутинг
$map = array('/#method|add|sub|div|mul#/#a|[+-]?[0-9]*.?[0-9]+([eE][+-]?[0-9]+|)#/#b|[+-]?[0-9]*.?[0-9]+([eE][+-]?[0-9]+|)#' => 'AlephDemoArithmetic->route', 
             '/rom2dec/#x|(?i)M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])#' => 'AlephDemoTransform->rom2dec', 
             '/dec2rom/#x|[1-9]{1}[0-9]{0,6}#' => 'AlephDemoTransform->dec2rom', 
             '/#method|akkerman|gcd#/#a|[0-9]+#/#b|[0-9]+#' => 'AlephDemoMisc->route',
             '/sets/#vars|[0-9a-zA-Z/]+#' => 'AlephDemoMisc->sets');

// привязываем к маршрутам автоматические действия
foreach ($map as $url => $act) $a->bind($url, $act);

// выполняем поиск действия для получения результата
$result = $a->route();

// отдаём ответ на основе результата
if ($result !== null) 
{
  $a->response()->stop(200, $result);
}
else 
{
  $a->response()->stop(404, file_get_contents('404.html'));
}

Карта маршрутов — массив, ключами которого являются регулярные выражения, соответствующие запросу, причём ключи могут содержать переменные (#method|...#, #a|...#) которые потом будут использованы как именованные параметры, а значениями — соответствующие методы необходимых классов.

Примеры валидных вызовов, согласно маршрутам:
http://demo.4leph.com/rom2dec/MMDCXCVIII [2] (перевод из римской в десятичную)
http://demo.4leph.com/dec2rom/2012 [3] (перевод из десятичной в римскую)
http://demo.4leph.com/sets/hab/ra/habr [4] (генерация вариантов множеств из указаных данных)
http://demo.4leph.com/akkerman/3/3 [5] (вычисление функции Аккермана, значения параметров ограничены максимальными 3 и 3, цель метода — показать работу с кэшированием результатов вместо постоянного вычисления)
http://demo.4leph.com/add/1243.454e+45/-2.45 [6] (вычисление нехитрым калькулятором)

Естественно вместо этих, представленных намеренно, академических примеров могли бы быть, набивших оскомину, /product/1532/details/a-title-of-product, и даже более того, можно без проблем реализовать разную выдачу по запросам /product/1532/details/a-title-of-product, /product/1532/details/a-title-of-product.xml, /product/1532/details/a-title-of-product.json и в том же духе. Всё это очень просто реализуется, как вы уже могли заметить.

Остановимся подробнее на выполнении

$result = $a->route();

При запросе вида demo.4leph.com/add/1243.454e+45/-2.45 [6] будет вызван метод AlephDemoArithmetic->route с параметрами 'add', '1243.454e+45' и '-2.45' Смотрим же реализацию метода (файл app/engine/arithmetic.php):

<?php

namespace AlephDemo;

class Arithmetic extends Calculator
{
  public function add($a, $b)
  {
    return $a + $b;
  }
 
  public function sub($a, $b)
  {
    return $a - $b;
  }
  
  public function mul($a, $b)
  {
    return $a * $b;
  }
  
  public function div($a, $b)
  {
    if ($b == 0) return 'Error: the second argument cannot be zero.';
    return $a / $b;
  }
}

Класс Arithmetic в свою очередь наследуется от класса Calculator, который реализует метод route:

<?php

namespace AlephDemo;

class Calculator
{
  public function route($method, $a, $b)
  {
    if (method_exists($this, $method)) 
    {
      return call_user_func_array(array($this, $method), array($a, $b));
    }
    return 'Error: method "' . $method . '" doesn't exist in class "' . get_class($this) . '"';
  }
}

Кажется, тут всё очевидно и не должно вызывать вопросов.

Обратите внимание, что метод sets принимает в качестве единственного аргумента строку, идущую после sets/ в запросе, и эти данные обрабатывает самостоятельно. Гибкость роутера налицо, и в таком виде он способен используя минимум действий заменить, к примеру, маршртуизацию Yii, являющуюся не в пример сложнее, при том, что там маршруты жёстко закреплены за контроллерами и действиями.

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

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

Больше информации о содержимом ядра на официальном сайте, в разделах Справочник Классов [7] и Документация [8].

Вместо заключения

Хочется ещё раз заметить, что опубликованная часть это пока что только ядро. Не стоит бросаться в сравнения и спрашивать чем это лучше известных решений, требовать тестов производительности и прочее. На подходе к публикации и ORM и Page Object Model и всё остальное. Когда на рынке php полно решений сделанными одними профессионалами для других, очень не хватает решения, сделанного профессионалами для непрофессионалов чтобы сделать их работу более профессиональной.

Официальный сайт [9]
Репозиторий на GitHub [10]
Демо пример [11]
Пустой пока форум, ожидающий первых посетителей [12]

Автор: AlephTav


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/web-razrabotka/7328

Ссылки в тексте:

[1] http://habrahabr.ru/post/141477/: http://habrahabr.ru/post/141477/

[2] http://demo.4leph.com/rom2dec/MMDCXCVIII: http://demo.4leph.com/rom2dec/MMDCXCVIII

[3] http://demo.4leph.com/dec2rom/2012: http://demo.4leph.com/dec2rom/2012

[4] http://demo.4leph.com/sets/hab/ra/habr: http://demo.4leph.com/sets/hab/ra/habr

[5] http://demo.4leph.com/akkerman/3/3: http://demo.4leph.com/akkerman/3/3

[6] http://demo.4leph.com/add/1243.454e+45/-2.45: http://demo.4leph.com/add/1243.454e+45/-2.45

[7] Справочник Классов: http://4leph.com/ru/api

[8] Документация: http://4leph.com/ru/documentation

[9] Официальный сайт: http://4leph.com/ru/home

[10] Репозиторий на GitHub: https://github.com/AlephTav/Aleph

[11] Демо пример: http://demo.4leph.com

[12] Пустой пока форум, ожидающий первых посетителей: http://4leph.com/app/smf/index.php