Trzy rodzaje tagów Twig
{# komentarz — nie trafia do HTML #}
{{ zmienna }}
{{ artykul.tytul }}
{{ user.getName() }}
{% if warunek %}...{% endif %}
{% for item in kolekcja %}...{% endfor %}
{% block content %}...{% endblock %}
Dziedziczenie layoutów
To najważniejsza funkcja Twig — unikasz powielania HTML:
{# templates/base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}FactoryCode{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
{# templates/blog/show.html.twig #}
{% extends 'base.html.twig' %}
{% block title %}{{ article.title }} — Blog{% endblock %}
{% block body %}
<h1>{{ article.title }}</h1>
<div class="content">
{{ article.content|markdown }}
</div>
{% endblock %}
Filtry
{{ 'hello world'|upper }} {# HELLO WORLD #}
{{ 'HELLO'|lower }} {# hello #}
{{ article.content|length }} {# liczba znaków #}
{{ article.content|truncate(200) }} {# skróć do 200 znaków #}
{{ price|number_format(2, ',', ' ') }} {# 1 234,56 #}
{{ date|date('d.m.Y H:i') }} {# 23.06.2025 14:30 #}
{{ article.content|nl2br }} {# \n → <br> #}
{{ article.content|markdown }} {# Markdown → HTML #}
{{ rawHtml|raw }} {# wyłącz escapowanie #}
Warunki i pętle
{% if article.isPublished %}
<span class="badge bg-success">Opublikowany</span>
{% elseif article.status == 'draft' %}
<span class="badge bg-secondary">Szkic</span>
{% else %}
<span class="badge bg-warning">{{ article.status }}</span>
{% endif %}
{% for tag in article.tags %}
<span class="tag">#{{ tag.name }}</span>
{% else %}
<span class="text-muted">Brak tagów</span>
{% endfor %}
Makra — wielokrotne użycie
{% macro alert(message, type = 'info') %}
<div class="alert alert-{{ type }}">
{{ message }}
</div>
{% endmacro %}
{# użycie #}
{{ _self.alert('Artykuł zapisany!', 'success') }}
{{ _self.alert('Błąd walidacji', 'danger') }}
include vs embed
{# include — wstawia szablon, dziedziczy wszystkie zmienne #}
{% include 'components/_card.html.twig' with {article: article} %}
{# embed — wstawia szablon i pozwala nadpisywać jego bloki #}
{% embed 'components/_modal.html.twig' %}
{% block title %}Potwierdzenie usunięcia{% endblock %}
{% block body %}Czy na pewno chcesz usunąć ten artykuł?{% endblock %}
{% endembed %}
Własne rozszerzenie Twig
// src/Twig/AppExtension.php
class AppExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('reading_time', function (string $content): int {
$words = str_word_count(strip_tags($content));
return (int) ceil($words / 200); // ~200 słów/min
}),
];
}
}
{# użycie #}
<span>{{ article.content|reading_time }} min czytania</span>