Содержание
PHP On Rails - MVC-фреймворк для построения веб-приложений на языке PHP.
Фреймворк создан в целях обучения, но предлагает некоторые продвинутые опции, такие как гибкая система маршрутизации и экшен-фильтры. Основой для представлений является шаблонизатор Twig.
Поставленная цель - создание с нуля фреймворка полностью базирующегося на паттерне Модель-Представление-Контроллер.
Не смотря на то, что PHP On Rails в первую очередь учебный проект, он полностью работоспособен и готов к построению приложений.
На базе PHP On Rails выполнено полноценное приложение-блог - myPosts.
В myPosts реализованы: системы авторизации/аутентификации, рассылка уведомлений на почту, хранение данных (локально и на базе AWS S3), восстановление пароля, защита от спама, работа с хэштегами, админ-панель и другой функционал.
Установка PHP On Rails предлагается в двух вариантах: сборки в Docker и локальной установки.
Прежде всего, необходимо склонировать репозиторий
$ git clone https://github.com/IlyaMur/php_on_rails_mvc.git
$ cd php_on_rails_mvc
И подготовить файл .env
$ make env-prepare
Опционально, изменить параметры БД и сервера в файле .env
MYSQL_USER='user'
MYSQL_HOST='mariadb'
APACHE_DEFAULT_PORT='80'
MYSQL_PASSWORD='testpassword'
...
Приложение доступно для удобной сборки в Docker.
Собрать и запустить приложение
$ make docker-start
Остановить и удалить контейнеры
$ make docker-stop
Так же доступны:
$ make docker-bash # запустить сессию bash в контейнере
$ make docker-test # запустить тесты в контейнере
По умолчанию приложение будет доступно: http://localhost
PHP >= 8.0
Для установки зависимостей:
$ make install
В настройках веб-сервера установить root в директории public/
Опционально, из файла database/php_on_rails_demo_db.sql
импортировать дамп базы-примера в выбранную СУБД.
Для человекопонятных URL необходимы настройки rewrite rules сервера. .htaccess файл доступен в директории public
.
Настройки конфигурации доступны в файле config/config.php
.
Настройки по умолчанию включают в себя:
- Данные подключения к БД.
- Логирование ошибок.
- Установки для вывода/скрытия детализации ошибок.
Для переопределения настроек в конфигурационном файле доступны соответствующие константы.
В процессе создания фреймворка стояла цель написания решений с нуля.
Зависимости PHP On Rails:
- Twig Template Engine.
- vlucas/phpdotenv.
Маршрутизатор распознает запрошенный URL и вызывает соответствующий экшн (метод) определенного контроллера. Маршруты добавляются в фронт контроллер.
В качестве примера доступен маршрут, который соответствует экшену index
в Home controller.
Маршруты добавляются методом add
. Возможно добавление фиксированных маршрутов с определением конкретного контроллера и экшена:
// При запросе на root, будет вызван метод index, контроллера Home.
$router->add('', ['controller' => 'Home', 'action' => 'index']);
// При запросе на posts/index, будет вызван метод index, контроллера Posts.
$router->add('posts/index', ['controller' => 'Posts', 'action' => 'index']);
Так же возможно определение гибких маршрутов, с переменными controller и action:
// В данном случае маршрутизатор будет сопоставлять доступные контроллеры и экшены с указанными в запросе
$router->add('{controller}/{action}');
В дополнение к переменным controller и action возможно определить любой желаемый параметр поставив его в фигурные скобки, так же определив для него регулярное выражение:
// В данном случае параметр: id.
$router->add('{controller}/{id:\d+}/{action}');
// Для маршрутизации к определенному посту с помощью его id.
$router->add('posts/{action}/{id:\d+}', ['controller' => 'posts']);
Доступно определение неймспейса для контроллера, что может быть удобно для создания "админок":
$router->add('admin/{controller}/{action}', ['namespace' => 'Admin']);
В PHP On Rails контроллеры - это классы с наследованием от класса Базового Контроллера src\Controllers\BaseController.php
Контроллеры хранятся в директории src/Controllers
. Как образец доступен Home controller.
Классы контроллеров должны находиться в неймспейсе Ilyamur\PhpOnRails\Controllers
.
Доступно добавление поддиректорий для организации контроллеров, для этого при добавлении маршрута необходимо указать и неймспейс (описано в секции маршрутизации)
Классы контроллеров содержат методы - экшены.
Чтобы создать экшен, необходимо добавить суффикс Action
к имени метода. В контроллере src/Controllers/Home.php, доступном для образца, таким образом определен экшен index
В контроллерах доступны параметры маршрута (для примера: параметр id). Для доступа к ним в экшенах необходимо обратиться к свойству $this->route_params
Контроллеры могут иметь методы-фильтры before и after. Эти методы вызываются до и после каждого экшена в контроллере.
Вызов экшен-фильтров осуществлен через магический метод __call
определенный в BaseController.
Экшен-фильтры могут быть очень полезны, например, для аутентификации, когда необходимо убедиться, что пользователь совершил логин до того как вызывать необходимый экшен.
Добавление экшен фильтров опционально.
Для before-фильтра добавление выглядит так:
/**
* Before-фильтр. При переопределении в наследнике может возвращать false.
* Для предовращения исполнения экшена обозначенного маршрутизатором.
*/
protected function before()
{
// ...
}
Добавление after-фильтра:
/**
* After-фильтр. Выполняется после обозначенного маршрутизатором экшена.
*/
protected function after()
{
// ...
}
В PHP On Rails представления помещаются в директорию src/Views
.
Основным форматом для представлений выбран шаблонизатор Twig. Выбор был сделан на основе удобства и гибкости данного движка.
Twig предоставляет более безопасные (с защитой от XSS) и простые шаблоны с возможностью наследования.
Пример рендера представления с передачей в него данных:
BaseView::renderTemplate('Home/index', [
'name' => 'John Doe',
'colors' => ['red', 'green', 'blue'],
]);
Образец шаблона представления находится в src/Views/Home/index.html.twig, данный шаблон наследуется от базового шаблона src/Views/base.html.twig.
В PHP On Rails модели наследуются от класса BaseModel
и используют PDO для доступа к БД.
Модели хранятся в директории src/Models
. В качестве образца доступна модель src/Models/User.php.
Получить инстанс подключения к базе данных с помощью PDO:
$db = static::getDB();
Ошибки преобразуются в исключения. Обработчиками обозначены:
set_error_handler('Ilyamur\PhpOnRails\Service\ErrorHandler::errorHandler');
set_exception_handler('Ilyamur\PhpOnRails\Service\ErrorHandler::exceptionHandler');
При константе SHOW_ERRORS
(настраивается в config.php) равной true
, в случае исключения или ошибки в браузер будет выведена полная детализация.
Если SHOW_ERRORS
присвоено значение false
будет показано лишь общее сообщение из шаблонов 404.html.twig или 500.html.twig в зависимости от ошибки.
Детализированная информация в данном случае будет логироваться в директории logs/
.
Не смотря на то, что фреймворк протестирован и находится в полностью работоспособном состоянии, очевидны места для дальнейшего улучшения.
Видимый на данный момент To-Do List:
- Переработка в сторону DI класса
BaseModel
. Доступные на данный момент модели тестируются не лучшим образом. - Альтернатива методу
__call
в классеBaseController
. Данное возможное улучшение позволит коду стать более прозрачным.