Object-Oriented Templates

PHP Classes that render: Twig Components

Create reusable, object-oriented templates. PHP class + template = Twig components.

composer require symfony/ux-twig-component

What Twig Components gives you

  • Classes that render

    A PHP class backing every Twig template.

  • Typed props

    Declare inputs once, get defaults and validation.

  • Named blocks

    Override any part of a component from outside.

  • Anonymous components

    Skip the class when a template is enough.

  • Composable by design

    Nest components and pass attributes through.

Render Reusable UI Elements

Add Twig Components to your app.

Create PHP classes that can render themselves

src/Twig/Components/Alert.php
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent]
final class Alert
{
    public ?string $variant = null;

    public function getIcon(): string
    {
        return match ($this->variant) {
            'danger' => 'bi:exclamation-circle',
            'warning' => 'bi:exclamation-triangle',
            'info' => 'bi:info-circle',
            default => 'bi:check-circle',
        };
    }
}
{#- Alert / message box. Variants via html_cva; content passed as the default slot. -#}
{%- set style = html_cva(
    base: 'flex items-center gap-2 rounded-md border p-4',
    variants: {
        variant: {
            success: 'border-green-200 bg-green-100 text-green-800 dark:border-green-900 dark:bg-green-950 dark:text-green-300',
            danger: 'border-red-200 bg-red-100 text-red-800 dark:border-red-900 dark:bg-red-950 dark:text-red-300',
            warning: 'border-yellow-200 bg-yellow-100 text-yellow-800 dark:border-yellow-900 dark:bg-yellow-950 dark:text-yellow-300',
            info: 'border-blue-200 bg-blue-100 text-blue-800 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-300',
        },
    },
) -%}
<div class="{{ style.apply({variant: variant}, attributes.render('class'))|tailwind_merge }}" role="alert" {{ attributes.without('class') }}>
    <twig:ux:icon name="{{ this.icon }}" class="Icon shrink-0" />
    <span>{% block content %}{% endblock %}</span>
</div>
Symfony logo

UX Twig Components

<twig:Alert variant="info">
    This is an informational message.
</twig:Alert>
<twig:Alert variant="success">
    Your changes were saved.
</twig:Alert>
<twig:Alert variant="warning">
    Your session will expire in a few minutes.
</twig:Alert>
<twig:Alert variant="danger">
    Oh no! The dinos escaped!
</twig:Alert>

A class, a template, some props

How a component is put together.

A Twig Component is a PHP class paired with a template. The class owns the data, the template owns the markup, and neither one knows about controllers.

A class and a template

Public properties become the inputs. The matching Twig file next to it renders them.

#[AsTwigComponent]
final class Alert
{
    public string $variant = 'info';
    public string $message;
}

Props and attributes

Simple components skip the class entirely. Anything you pass beyond the declared props lands on the root element.

{% props variant = 'info' %}

<div {{ attributes.defaults({
    class: 'Alert Alert--' ~ variant,
}) }}>
    {% block content %}{% endblock %}
</div>

Hooks before rendering

PreMount and PostMount let the class normalise or compute data once, before the template sees it.

#[PreMount]
public function preMount(array $data): array
{
    $data['message'] = trim($data['message']);

    return $data;
}

Install Twig Components.

$ composer require symfony/ux-twig-component

More from Symfony UX.

Twig Components is one package among many. They share the same Stimulus foundation and install the same way.

Image for the Icons UX package

Icons

Render SVG icons seamlessly from your Twig templates.

Image for the Map UX package

Map

Render interactive Maps in PHP with Leaflet or Google Maps.

Image for the Live Components UX package

Live Components

Build dynamic interfaces with zero JavaScript

Browse every package

Keep Twig Components at hand.

Documentation, the people behind it, and where to ask when something does not behave.