Как использовать Twig в Symfony?php-80

1. Установка и базовая настройка

Twig автоматически устанавливается с Symfony, но если нужно добавить отдельно:

composer require twig

Конфигурация по умолчанию (config/packages/twig.yaml):

twig:
    default_path: '%kernel.project_dir%/templates'
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    form_themes: ['bootstrap_5_layout.html.twig']

2. Структура шаблонов

Рекомендуемая структура папок:

templates/
├── base.html.twig          # Базовый шаблон
├── components/             # Компоненты
├── pages/                  # Страницы
│   ├── blog/
│   │   ├── index.html.twig
│   │   └── show.html.twig
└── macros/                 # Макросы

3. Базовый шаблон

Пример base.html.twig:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}My App{% endblock %}</title>
    {% block stylesheets %}
        {{ encore_entry_link_tags('app') }}
    {% endblock %}
</head>
<body>
    {% include 'components/header.html.twig' %}

    <main class="container">
        {% block body %}{% endblock %}
    </main>

    {% include 'components/footer.html.twig' %}

    {% block javascripts %}
        {{ encore_entry_script_tags('app') }}
    {% endblock %}
</body>
</html>

4. Наследование шаблонов

Пример страницы, расширяющей базовый шаблон:

{% extends 'base.html.twig' %}

{% block title %}Blog Posts{% endblock %}

{% block body %}
    <h1>Latest Posts</h1>

    {% for post in posts %}
        <article>
            <h2>{{ post.title }}</h2>
            <p>{{ post.content|u.truncate(200) }}...</p>
        </article>
    {% endfor %}
{% endblock %}

5. Передача данных в шаблон

Из контроллера:

#[Route('/blog', name: 'blog_index')]
public function index(): Response
{
    $posts = $this->getDoctrine()
        ->getRepository(Post::class)
        ->findAll();

    return $this->render('pages/blog/index.html.twig', [
        'posts' => $posts,
        'page_title' => 'Blog Archive'
    ]);
}

6. Полезные возможности Twig

Фильтры:

{{ post.createdAt|date('d.m.Y H:i') }}
{{ user.description|striptags|upper }}
{{ price|format_currency('USD') }}

Функции:

{{ path('app_blog_show', {id: post.id}) }}
{{ asset('images/logo.png') }}
{{ csrf_token('authenticate') }}

Макросы :

{% macro input(name, value, type = 'text') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ _self.input('username') }}

7. Компоненты и include

Пример компонента templates/components/alert.html.twig:

<div class="alert alert-{{ type }}">
    {{ message }}
    {% if dismissible %}
        <button class="close">&times;</button>
    {% endif %}
</div>

Использование:

{% include 'components/alert.html.twig' with {
    type: 'success',
    message: 'Operation completed!',
    dismissible: true
} %}

8. Расширение Twig

Кастомный фильр:

  1. Создаем класс:
namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class AppExtension extends AbstractExtension
{
    public function getFilters()
    {
        return [
            new TwigFilter('excerpt', [$this, 'createExcerpt']),
        ];
    }

    public function createExcerpt(string $text, int $length = 50): string
    {
        if (mb_strlen($text) <= $length) {
            return $text;
        }
        return mb_substr($text, 0, $length) . '...';
    }
}
  1. Использование в шаблоне:
{{ post.content|excerpt(100) }}

9. Формы в Twig

Рендеринг формы:

{{ form_start(post_form) }}
    {{ form_errors(post_form) }}

    {{ form_row(post_form.title) }}
    {{ form_row(post_form.content) }}

    <button type="submit">Save</button>
{{ form_end(post_form) }}

10. Тестирование шаблонов

Установка тестовой среды:

composer require --dev twig/test

Пример теста:

use Twig\Test\IntegrationTestCase;

class TwigTest extends IntegrationTestCase
{
    public function getFixturesDir()
    {
        return __DIR__.'/Fixtures/';
    }
}

Резюмируем:

  1. Twig — это современный, безопасный шаблонизатор для Symfony

  2. Ключевые возможности:

    • Наследование шаблонов
    • Компонентный подход
    • Безопасное экранирование
    • Расширяемость через фильтры и функции
  3. Best Practices:

    • Используйте наследование для DRY
    • Выносите повторяющиеся элементы в компоненты
    • Применяйте макросы для сложных UI-элементов
    • Всегда экранируйте вывод ({{ }} делает это автоматически)
  4. Производительность:

    • Шаблоны компилируются в PHP-код
    • Поддерживается кэширование
    • В production включен авто-escape

Для сложных проектов:

  • Используйте namespaces для шаблонов
  • Настройте глобальные переменные
  • Создайте кастомные теги
  • Используйте встроенную поддержку Webpack Encore