Перейти к содержанию

Шаблоны

Пространство имён Keel\View. Для HTML контроллер возвращает строку (Responder отвечает text/html); ViewRenderer превращает шаблон в эту строку. Keel подключает Twig или Latte, оба — опциональные зависимости.

final class PageController
{
    public function __construct(private readonly ViewRenderer $views) {}

    #[Get('/')]
    public function home(): string
    {
        return $this->views->render('home.twig', ['title' => 'Hello']);
    }
}

Twig

composer require twig/twig
// config/views.php
return static fn(Env $env, string $projectDir): TwigConfig => new TwigConfig(
    paths: [$projectDir . '/templates'],
    cache: $projectDir . '/var/cache/twig',   // null: без скомпилированного кэша (разработка)
    debug: $env->bool('APP_DEBUG'),           // включает и auto_reload
    strictVariables: true,
    globals: ['app_name' => 'My app'],
);

// config/services.php
return new ServicesConfig([TwigProvider::class]);

TwigProvider регистрирует Twig\Environment (внедряйте его, чтобы добавить расширения, фильтры или функции в своём провайдере) и TwigRenderer как ViewRenderer. Twig экранирует HTML по умолчанию.

Latte

composer require latte/latte
// config/views.php
return static fn(Env $env, string $projectDir): LatteConfig => new LatteConfig(
    directory: $projectDir . '/templates',
    tempDirectory: $projectDir . '/var/cache/latte',  // null: компиляция в памяти процесса
    autoRefresh: $env->bool('APP_DEBUG'),
);

// config/services.php
return new ServicesConfig([LatteProvider::class]);

LatteProvider регистрирует Latte\Engine и LatteRenderer. Имена шаблонов — относительно каталога. Latte экранирует по контексту (HTML, атрибуты, JavaScript) по умолчанию.

Worker mode

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

Переводы

Если зарегистрирован Translator (Локализация), оба провайдера добавляют фильтр и функцию trans и locale(): {{ 'cart.items'|trans({count: 3}) }}.

Другие движки

Реализуйте ViewRenderer поверх своего движка и назначьте алиас в провайдере:

$definitions->set(BladeRenderer::class)->alias(ViewRenderer::class);