symfony/twig-bridge
Symfony Twig Bridge integrates Twig with Symfony components, providing templating support across the framework. Includes extensions, form rendering helpers, and tooling to use Twig seamlessly in Symfony applications, with links to docs, issues, and contributions.
Installation:
composer require symfony/twig-bridge
Ensure twig/twig is also installed (required dependency).
Basic Configuration:
In config/app.php, register the Twig bridge as a service provider (if not auto-discovered):
'providers' => [
// ...
Symfony\Bridge\Twig\TwigBridgeServiceProvider::class,
],
First Use Case: Render a Symfony form in a Twig template:
{{ form_start(form) }}
{{ form_row(form.field) }}
{{ form_end(form) }}
Pass the form from your Laravel controller:
return view('template', ['form' => $form]);
Key Files to Explore:
config/packages/twig.yaml (Symfony’s default Twig config, adaptable for Laravel).vendor/symfony/twig-bridge/Resources/views/Form/ (default form themes).app/Views/ (your custom Twig templates).Dynamic Form Themes:
Override Symfony’s default form themes by creating a form_theme.html.twig in your resources/views/:
{# app/Resources/views/form_theme.html.twig #}
{% block form_row %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock %}
Register it in your controller:
$form->setTheme([new \Twig\Template\TemplateName('form_theme.html.twig')]);
Validation-Focused Workflow: Leverage Symfony’s validation helpers in Twig:
<input type="text"
{{ form_widget(form.field, { 'attr': {'aria-invalid': form.field.vars.errors|length > 0} }) }}>
access_decider in Twig:
{% if app.security.authorization_checker.access_decision('ROLE_ADMIN') == 'granted' %}
<a href="/admin">Admin Panel</a>
{% endif %}
Or with the Twig extension:
{% if app.security.access_decision('ROLE_USER') == 'granted' %}
{# User-specific content #}
{% endif %}
{{ 'welcome.message'|trans({'%name%': user.name}) }}
Configure the translator in config/services.php:
'translator' => [
'default_locale' => 'en',
'fallback_locale' => 'en',
'paths' => [__DIR__.'/../resources/translations'],
],
config/services.php:
'twig' => [
'globals' => [
'app' => App::class, // Your custom service
],
],
Use in Twig:
{{ app.someMethod() }}
TemplatedEmail with Twig:
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
$email = (new TemplatedEmail())
->from('sender@example.com')
->to('user@example.com')
->subject('Welcome!')
->htmlTemplate('emails/welcome.html.twig')
->context(['name' => 'John']);
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class AppExtension extends AbstractExtension
{
public function getFunctions(): array
{
return [
new TwigFunction('app_function', [$this, 'doSomething']),
];
}
public function doSomething(): string
{
return 'Custom logic here';
}
}
Register it in config/services.php:
'twig' => [
'extensions' => [App\Twig\AppExtension::class],
],
Use in Twig:
{{ app_function() }}
Caching Conflicts:
config/packages/twig.yaml:
twig:
cache: '%kernel.cache_dir%/twig'
Form Theme Overrides:
{% extends 'form_div_layout.html.twig' %}
Symfony-Specific Assumptions:
Container or Kernel (e.g., app.security).$this->app->bind('security.authorization_checker', function ($app) {
return new LaravelAuthorizationChecker(); // Custom implementation
});
Deprecated Methods:
phpdocumentor/reflection-docblock may cause conflicts (e.g., v6+).composer.json:
"require": {
"phpdocumentor/reflection-docblock": "^5.3"
}
Block Prefix Leaks:
block_name_0, block_name_1).Bootstrap 4 Form Layouts:
Enable Twig Debugging:
Set debug: true in config/packages/twig.yaml:
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
Check Template Inheritance:
Use {{ dump(_context) }} to inspect the template context and inheritance chain.
Symfony Profiler Integration:
Install symfony/web-profiler-bundle for Twig template profiling:
composer require symfony/web-profiler-bundle
Form Debugging: Enable form debugging in Twig:
{{ form(form, { 'attr': {'data-form-debug': true} }) }}
Custom Form Types: Extend Symfony’s form types for Laravel:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class LaravelFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('field', TextType::class);
}
}
Register it in config/services.php:
'form.types' => [
'laravel_form' => App\Form\LaravelFormType::class,
],
Twig Runtime Integration:
Override Symfony’s TwigRuntime for custom logic:
namespace App\Bridge\Twig;
use Symfony\Bridge\Twig\Extension\TwigExtension;
use Symfony\Bridge\Twig\TwigRuntime;
class CustomTwigRuntime extends TwigRuntime
{
public function customMethod()
{
return 'Custom runtime logic';
}
}
Bind it in config/services.php:
'twig.runtime' => App\Bridge\Twig\CustomTwigRuntime::class,
Event Listeners:
Listen to Twig events (e.g., Twig\EventDispatcher\TemplateEvents::PRE_RENDER):
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Twig\EventDispatcher\TemplateEvents;
class TwigEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
TemplateEvents::PRE_RENDER => 'onPreRender',
];
}
public function onPreRender
How can I help you explore Laravel packages today?