Макет и ссылки в шаблонах
У всех страниц сайта общие части: заголовок документа, меню, подвал. Чтобы не повторять их в каждом шаблоне, общую разметку выносят в макет (layout) — базовый шаблон с «окнами», которые заполняют отдельные страницы.
Макет
Создайте файл templates/layout.twig:
{# templates/layout.twig #}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>{% block title %}Блог{% endblock %}</title>
</head>
<body>
<main>{% block content %}{% endblock %}</main>
</body>
</html>block — именованное окно. У блока title есть содержимое по умолчанию, блок content пуст.
Страница на основе макета
Перепишите шаблон главной страницы:
{# templates/home.twig #}
{% extends 'layout.twig' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
<p>Сайт работает на Slim.</p>
{% endblock %}Строка extends сообщает, какой макет взять, а блоки заполняют его окна. Действие менять не нужно: оно по-прежнему выводит home.twig. Откройте главную страницу и посмотрите её исходный код — в нём появилась полная разметка документа.
Ссылки по именам маршрутов
Пакет slim/twig-view добавляет в шаблоны функцию url_for() — она строит адрес по имени маршрута, как urlFor() в коде. Добавьте в макет меню перед тегом main:
{# templates/layout.twig #}
<nav>
<a href="{{ url_for('home') }}">Главная</a>
<a href="{{ url_for('posts.index') }}">Статьи</a>
</nav>Меню появится на всех страницах, которые наследуют макет. Параметры адреса передают вторым аргументом:
{# templates/posts/index.twig #}
{% extends 'layout.twig' %}
{% block content %}
<h1>Статьи</h1>
{% for post in posts %}
<p><a href="{{ url_for('posts.show', {id: post.id}) }}">{{ post.title }}</a></p>
{% endfor %}
{% endblock %}Каждый заголовок станет ссылкой вида /posts/1.
| Функция | Что возвращает |
|---|---|
url_for('posts.show', {id: 5}) | Адрес по имени маршрута |
full_url_for('posts.show', {id: 5}) | То же с именем сайта |
current_url() | Адрес текущей страницы |
is_current_url('posts.index') | Совпадает ли текущий адрес с маршрутом |
Общие данные
Значение, нужное во всех шаблонах, например имя сайта из настроек, добавляют один раз — там, где создаётся Twig:
// config/container.php
use Psr\Container\ContainerInterface;
use Slim\Views\Twig;
Twig::class => function (ContainerInterface $c) {
$twig = Twig::create(__DIR__ . '/../templates', ['cache' => false]);
$twig->getEnvironment()->addGlobal('site_name', $c->get('settings')['site_name']);
return $twig;
},Теперь в любом шаблоне доступна переменная site_name: замените слово «Блог» в блоке title макета на {{ site_name }}.
Шаблоны на PHP
Если отдельный язык шаблонов не нужен, есть пакет slim/php-view: шаблоны в нём — обычные файлы PHP. Обезвреживать вывод там приходится вручную функцией htmlspecialchars(), поэтому в курсе используется Twig.
Частая ошибка
В шаблоне с extends всё, что написано вне блоков, вызывает ошибку Twig: дочерний шаблон может только заполнять блоки макета. Если страница пустая или падает после добавления extends, проверьте, что вся разметка находится внутри block content.