Twig: макросы, свои фильтры, глобальные переменные
Когда шаблонов становится много, в них появляются повторы: одинаковые поля форм, одно и то же форматирование цены, боковая колонка на каждой странице. В Twig есть средства, чтобы описать каждую такую вещь один раз.
Переменные в шаблоне
{% set total = price * quantity %}
<p>Итого: {{ total }}</p>Тесты и операторы
{% if user is defined and user.name is not empty %}
{{ user.name }}
{% endif %}
{{ post.subtitle ?? 'Без подзаголовка' }}
{{ 'Привет, ' ~ user.name }}
{{ loop.index is even ? 'even' : 'odd' }}Знак ~ соединяет строки, ?? подставляет значение вместо отсутствующего.
Макросы
Макрос — функция, возвращающая разметку:
{# templates/_macros.html.twig #}
{% macro badge(text, color = 'gray') %}
<span class="badge badge-{{ color }}">{{ text }}</span>
{% endmacro %}{% import '_macros.html.twig' as ui %}
{{ ui.badge('Новое', 'green') }}
{{ ui.badge('Черновик') }}Свой фильтр
Фильтры и функции добавляет класс-расширение:
// src/Twig/AppExtension.php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class AppExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('price', $this->formatPrice(...)),
];
}
public function formatPrice(float $amount): string
{
return number_format($amount, 2, ',', ' ') . ' ₽';
}
}{{ product.price|price }}Регистрировать класс не нужно: Symfony находит расширения сам. Функции добавляют так же — методом getFunctions() и классом TwigFunction.
Глобальные переменные
Значения, нужные во всех шаблонах, задают в настройках:
# config/packages/twig.yaml
twig:
globals:
site_name: 'Мой блог'
support_email: 'help@example.com'<footer>{{ site_name }} · {{ support_email }}</footer>Встроенная переменная app уже содержит полезное: app.user, app.request, app.session, app.environment.
Встраивание контроллера
Блоку «Последние статьи» в боковой колонке нужны данные на каждой странице. Чтобы не передавать их из каждого контроллера, блок выводят отдельным запросом внутри шаблона:
<aside>
{{ render(controller('App\\Controller\\SidebarController::recent', {limit: 5})) }}
</aside>Отладка
{{ dump(post) }}dump() показывает содержимое переменной. Без аргументов — все переменные шаблона.
Частая ошибка
В шаблоне не место сложным вычислениям и запросам к базе. Если в Twig появляются длинные цепочки условий и расчётов, перенесите их в контроллер, метод сущности или свой фильтр. Шаблон должен только показывать готовые данные.