Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Шаблоны Twig

До сих пор HTML собирался строками внутри действий. Это неудобно и опасно: легко забыть обезвредить чужой текст. Шаблон — отдельный файл с разметкой, в который действие передаёт данные. В Slim шаблонизатора нет; обычно подключают Twig.

Установка

composer require slim/twig-view

Где лежат шаблоны

Создайте вручную папку templates в корне проекта — рядом с config и src. Файлы шаблонов имеют расширение .twig.

Twig в контейнере

Объект шаблонизатора описывают в config/container.php, чтобы действия получали его через конструктор:

// config/container.php
use Slim\Views\Twig;
 
return [
    // ... прежние записи
 
    Twig::class => fn () => Twig::create(__DIR__ . '/../templates', ['cache' => false]),
];

Первый аргумент — папка с шаблонами. Кеш пока выключен; его включают при размещении на сервере.

Затем добавьте посредник пакета в config/middleware.php, выше трёх встроенных:

// config/middleware.php
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
 
$app->add(TwigMiddleware::createFromContainer($app, Twig::class));

Посредник нужен, чтобы в шаблонах работали функции для ссылок на маршруты.

Первый шаблон

{# templates/home.twig #}
<h1>{{ title }}</h1>
<p>Сайт работает на Slim.</p>

Двойные фигурные скобки выводят значение переменной. Первая строка — комментарий Twig, на страницу он не попадает.

Вывод из действия

// src/Action/HomeAction.php
namespace App\Action;
 
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Views\Twig;
 
final class HomeAction
{
    public function __construct(private Twig $twig) {}
 
    public function __invoke(Request $request, Response $response): Response
    {
        return $this->twig->render($response, 'home.twig', [
            'title' => 'Мой блог',
        ]);
    }
}

Метод render() принимает ответ, имя файла относительно папки templates и массив данных. Он записывает готовую страницу в ответ и возвращает его. Описание HomeAction::class из урока о настройках удалите из config/container.php: теперь действие создаётся автосвязыванием. Откройте главную страницу — на ней заголовок «Мой блог».

Синтаксис Twig

ЗаписьНазначение
{{ title }}Вывести значение
{{ post.title }}Элемент массива или свойство объекта
{% if ... %}, {% for ... %}Условие и цикл
{# ... #}Комментарий

Список в шаблоне

Перенесём в шаблон список статей. Создайте папку templates/posts и файл в ней:

{# templates/posts/index.twig #}
<h1>Статьи</h1>
 
{% for post in posts %}
    <p>{{ post.title }}</p>
{% else %}
    <p>Статей пока нет.</p>
{% endfor %}
// src/Action/ListPostsAction.php
public function __invoke(Request $request, Response $response): Response
{
    return $this->twig->render($response, 'posts/index.twig', [
        'posts' => $this->posts->all(),
    ]);
}

В конструктор действия добавляется private Twig $twig. По адресу /posts появится список; ветка else у цикла сработает, если массив пуст.

Частая ошибка

Twig сам обезвреживает HTML в выводимых значениях — это защита от чужих скриптов. Фильтр raw её отключает: {{ comment.text|raw }} выведет чужой тег <script> как есть. Применяйте raw только к разметке, которую создали сами.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.