Примечание переводчика: данная статья является переводом поста из блога компании Prosopo, разработчика Procaptcha - privacy-friendly альтернативы Google reCaptcha.
Мы рады представить вам наш новый пакет — PHP Views, Composer библиотеку, созданную в процессе работы над WordPress интеграцией для Procaptcha.
1. Что такое PHP Views?
PHP Views — это небольшой Composer пакет без зависимостей, созданный для того чтобы упростить работу с шаблонами в PHP. Он использует модельно-ориентированный подход, включает поддержку пространств имён и собственную реализацию Blade в качестве шаблонизатора по умолчанию.
Большинство PHP фреймворков имеет свои решения для шаблонов, но существует огромное количество PHP проектов, включая CMS вроде WordPress, где коробочные решения отсутствуют.
Обычные PHP шаблоны довольно многословны и подвержены ошибкам. PHP Views призван сделать работу с шаблонами в чистом PHP более простой, гибкой и надежной.
1.1) Несколько слов о Twig
Вы можете спросить: «А как же Twig от Symfony? Он ведь доступен как отдельный пакет!»
Это действительно так, и Twig — отличный инструмент. Однако он специализируется исключительно на шаблонах и не поддерживает модели. Это означает, что для передачи данных приходится использовать обычные массивы и строковые ключи.
Модельный подход в PHP Views решает эту проблему, добавляя в шаблоны преимущества объектно-ориентированного программирования.
Модели позволяют:
Использовать типизированные переменные — что гораздо надёжнее.
Инкапсулировать логику в методах моделей.
Избежать опечаток в ключах, которые сложно отследить при использовании строковых ключей в массивах.
Ещё один момент — в отличие от Blade, Twig не поддерживает нативный PHP-код и функции. Вместо этого приходится изучать его собственные фильтры и синтаксис, что может быть дополнительным препятствием.
О вкусах не спорят (no holy wars – just options)
У каждого инструмента есть плюсы и минусы. Мы использовали Twig в течение многих лет и ценим его сильные стороны. Но также видим и возможности для улучшения. И модельный подход из PHP Views может сделать ваш рабочий опыт с Twig ещё лучше.
1.2) Свобода выбора шаблонизатора
Возвращаясь к PHP Views: пакет включает собственный компилятор Blade и использует его по умолчанию.
Однако ключевой принцип пакета — гибкость. Вы можете подключить Twig или любой другой шаблонизатор всего за несколько строк кода — при этом сохранив преимущества модельного подхода и все функции, которые предлагает PHP Views.
1.3) Особенности автономной реализации Blade
Blade — это элегантный и мощный шаблонизатор, изначально созданный для Laravel. В отличие от Twig, он не ограничивает использование PHP, а наоборот — расширяет его возможности с помощью удобного синтаксиса, делая шаблоны проще и понятнее.
Blade предоставляет специальные сокращения, которые упрощают громоздкие конструкции, но при этом остаётся полноценным PHP с доступом ко всем его функциям.
К сожалению, Blade недоступен как отдельный пакет. Поэтому PHP Views включает собственную реализацию компилятора, которая поддерживает все ключевые функции Blade, при этом оставаясь полностью независимой от Laravel.
Возможно, вы встречали другие реализации, например jenssegers/blade, которые создают "заглушки" для Laravel зависимостей. Мы отказались от подобного подхода по нескольким причинам:
Требуется PHP 8.2 или выше.
Добавляются внешние зависимости.
Может ломаться интеграция при обновлениях Laravel (что уже случалось).
Нехватка гибкости — изначально реализация не создавалась как автономный компонент.
Использует глобальные функции Laravel, что мешает полной изоляции кода.
Благодаря отличной концепции Blade, наша реализация компилятора составила менее чем 200 строк кода.
2. Преимущества пакета
Прежде чем перейти к концепции и реализации, давайте посмотрим, что предлагает данный пакет:
Потрясающая производительность: Быстрее оригинального Blade из Laravel (см. бенчмарк ниже).
Отсутствие зависимостей: Лёгкая и простая интеграция в любой проект.
Широкая совместимость: PHP 7.4+, 8.0+
Надежная архитектура: Гибкая и модульная — можно легко переопределять компоненты под нужды проекта.
Поддержка пространств имён: Удобное управление различными шаблонизаторами через единый, структурированный подход.
Надёжность: каждый релиз проверен Pest тестами и PHPStan анализатором.
Несмотря на то, что список выше выглядит довольно обычно, настоящая сила PHP Views в его гибкости. Вы можете использовать пакет так, как необходимо именно вам:
В качестве поставщика шаблонов: Сочетайте модельно-ориентированный подход со встроенным движком Blade для создания простых и динамичных шаблонов.
Как самостоятельную Blade реализацию: Используйте нашу Blade реализацию для отображения своих Blade шаблонов.
Как модельный слой: Используйте модельно-ориентированный подход с любым шаблонизатором, например Twig или даже чистым PHP.
Как связующее звено: Объединяйте шаблоны, использующие разные движки, в единую систему.
2.1) Бенчмарк
Мы провели тест производительности PHP, чтобы сравнить PHP Views с Blade из Laravel (эмулируется через jenssegers/blade) и Twig. Ниже результаты для 1000 отображений:
Участник | Первый рендеринг, мс | Кешированный рендеринг, мс |
---|---|---|
prosopo/views (без моделей) | 19.75 | 19.75 (нет кеширования) |
prosopo/views (с моделями) | 43.78 | 43.78 (нет кеширования) |
illuminate/view (Blade из Laravel) | 181.24 | 56.77 |
twig/twig | 441.13 | 9.47 |
Цифры говорят сами за себя. Даже без кеша, с учётом дополнительных расходов на модели, реализация PHP Views значительно обгоняет конкурентов. Несмотря на мощный кеш в Twig, PHP Views быстрее, чем Blade из Laravel даже при кешировании.
Примечание: использовались следующие версии пакетов:
illuminate/view — 11.7.0
twig/twig — 3.17.1
jenssegers/blade — 2.0.1
Поскольку бенчмарк включён в репозиторий, вы можете легко запустить его локально:
git clone https://github.com/prosopo/php-views.git
composer install; cd benchmark; composer install
php benchmark {1000} — укажите количество отображений
3. Установка и минимальное использование
3.1) Установка
Поскольку PHP Views распространяется как Composer пакет, его установка просходит как обычно:
composer require prosopo/views
После установки убедитесь, что ваш проект подключает автозагрузчик Composer (если это ещё не сделано):
require __DIR__ . '/vendor/autoload.php';
3.2) Минимальная настройка
Для начала вам нужно создать три экземпляра: ViewTemplateRenderer, ViewNamespaceConfig и ViewsManager.
Основная конфигурация задаётся в ViewNamespaceConfig, где вы определяете папку с шаблонами и корневое пространство имён для моделей.
use Prosopo\Views\View\ViewNamespaceConfig;
use Prosopo\Views\View\ViewTemplateRenderer;
use Prosopo\Views\ViewsManager;
require __DIR__ . '/vendor/autoload.php';
// 1. Создаём рендерер шаблонов (по умолчанию используется встроенный Blade)
$viewTemplateRenderer = new ViewTemplateRenderer();
// 2. Конфигурация пространства имён
$namespaceConfig = (new ViewNamespaceConfig($viewTemplateRenderer))
->setTemplatesRootPath(__DIR__ . './templates')
->setTemplateFileExtension('.blade.php');
// 3. Создаём экземпляр менеджера представлений
$viewsManager = new ViewsManager();
// 4. Регистрируем пространство имён моделей
$viewsManager->registerNamespace('MyPackage\\Views', $namespaceConfig);
3.3) Определение модели
Теперь мы готовы создать первую модель. Как и во многих фреймворках (например, Laravel), здесь используется модельно-ориентированный подход к шаблонам.
Каждому шаблону соответствует своя модель. Публичные свойства и методы модели становятся доступными внутри шаблона как аргументы.
Класс модели должен расширять BaseTemplateModel или реализовывать интерфейс TemplateModelInterface:
namespace MyPackage\Views;
use Prosopo\Views\BaseTemplateModel;
class EmployeeTemplateModel extends BaseTemplateModel
{
public int $salary;
public int $bonus;
public CompanyTemplateModel $company;
public function total(): int
{
return $this->salary + $this->bonus;
}
}
Пример шаблона модели (используется Blade):
<p>
Ваш доход за месяц — {{ $total() }},
из них {{ $salary }} — зарплата, и {{ $bonus }} — бонус.
Расчёт налогов: {{ $company->calcTaxes($salary) }}
</p>
<p>Информация о компании:</p>
{!! $company !!}
Как видите, все публичные свойства модели доступны в шаблоне, включая вложенные модели, такие как $company. Вы также можете вызывать их публичные методы напрямую в шаблоне.
Класс BaseTemplateModel, от которого мы наследуемся, переопределяет метод __toString(), что позволяет отображать вложенные модели как строки через Blade вывод с поддержкой HTML.
Например: {!! $innerModel !!} отобразит модель как HTML-фрагмент.
Примечание: пакет не требует использовать суффикс Model в названиях классов. В этом примере он используется исключительно для наглядности.
3.4) Автоматическое сопоставление шаблонов
Встроенный ModelTemplateResolver автоматически сопоставляет шаблоны с моделями на основе имён классов и их пространств имён. Это избавляет от необходимости вручную указывать путь к шаблону.
Пример структуры:
src/
Views/
Homepage.php
Settings/
GeneralSettings.php
templates/
homepage.blade.php
settings/
general-settings.blade.php
Мы указываем корневую папку шаблонов и корневое пространство имён моделей в ViewNamespaceConfig (как делали выше):
$namespaceConfig = (new ViewNamespaceConfig($viewTemplateRenderer))
->setTemplatesRootPath(__DIR__ . './templates')
->setTemplateFileExtension('.blade.php');
$viewsManager = new ViewsManager();
$viewsManager->registerNamespace('MyPackage\Views', $namespaceConfig);
Примечание: имена шаблонов следует писать через дефисы. Имена моделей в стиле camelCase будут автоматически преобразованы в шаблоне в дефисы.
3.5) Использование
Экземпляр ViewsManager (который мы создали ранее) предоставляет методы createModel и renderModel.
Вы можете создать, настроить и отобразить модель за один шаг, указав callback-функцию в методе renderModel:
echo $viewsManager->renderModel(
EmployeeTemplateModel::class,
function (EmployeeTemplateModel $employee) use ($salary, $bonus) {
$employee->salary = $salary;
$employee->bonus = $bonus;
}
);
Пошаговое создание и отображение
Если вы хотите создать модель отдельно, используйте метод createModel, а отображение выполните позже:
$employee = $viewsManager->createModel(EmployeeTemplateModel::class);
$employee->salary = $salary;
$employee->bonus = $bonus;
echo $views->renderModel($employee);
Подсказка: вы также можете передавать callback как второй аргумент в методы createModel() и renderModel() — это позволяет настраивать модель перед возвратом или отображением.
Совет касательно типов аргументов
Класс ViewsManager реализует три интерфейса:
ViewNamespaceManagerInterface — для метода registerNamespace
ModelFactoryInterface — для метода createModel
ModelRendererInterface — для метода renderModel
Мы рекомендуем использовать эти интерфейсы как типы переменных в функциях, принимающих ViewsManager — это повышает читаемость и упрощает сопровождение кода.
Вот и всё! Сейчас вы уже готовы использовать данный пакет.
4. Заключение
Это был краткий обзор пакета PHP Views, созданного для упрощения работы с шаблонами в PHP. Если вас интересуют расширенные настройки, переопределение модулей и дополнительные возможности —загляните в официальный репозиторий.
Спасибо, что дочитали до конца! Надеемся, что данный пакет сделает вашу разработку проще и приятнее.
P.S. Если вам понравился PHP Views — поставьте ⭐️ его репозиторию на GitHub и поделитесь ссылкой с коллегами.