Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twig Bridge Laravel Package

symfony/twig-bridge

Symfony’s Twig Bridge integrates the Twig templating engine with Symfony components, providing extensions, loaders, form and translation support, and other glue code needed to use Twig seamlessly in Symfony-based applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require symfony/twig-bridge
    

    This package is typically auto-installed when using Symfony Flex or the Symfony Framework Bundle.

  2. First Use Case: Render a Twig template in a Symfony controller:

    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    
    class HomeController extends AbstractController
    {
        public function index(): Response
        {
            return $this->render('home/index.html.twig', [
                'name' => 'John Doe',
            ]);
        }
    }
    
    • Place the template at templates/home/index.html.twig.
    • Access Symfony services, routes, and assets directly in Twig (e.g., {{ path('app_home') }}).
  3. Where to Look First:

    • Symfony Docs: Twig Integration
    • TwigBridge Service: twig (auto-configured in Symfony).
    • Form Theming: templates/forms/ directory for custom form templates.

Implementation Patterns

Core Workflows

  1. Templating in Controllers:

    • Use render() or renderView() to return Twig responses.
    • Pass data as an associative array:
      return $this->render('template.html.twig', ['user' => $user]);
      
  2. Form Handling:

    • Automatically render forms with Symfony’s form theme:
      {{ form_start(form) }}
          {{ form_widget(form) }}
      {{ form_end(form) }}
      
    • Override form rendering in templates/forms/ (e.g., text_type.html.twig).
  3. Asset Management:

    • Use Twig’s asset() function for static files:
      <img src="{{ asset('images/logo.png') }}">
      
    • Configure asset versioning in config/packages/twig.yaml:
      twig:
          assets_version: 'unique123'
      
  4. Security Context:

    • Access the user and permissions via Twig globals:
      {% if is_granted('ROLE_ADMIN') %}
          Admin Panel
      {% endif %}
      
    • Use access_decision() (Symfony 7.4+) for granular checks:
      {% set decision = access_decision('edit', user) %}
      
  5. Email Templates:

    • Render emails with TemplatedEmail:
      $email = (new TemplatedEmail())
          ->from(new Address('sender@example.com', 'Sender'))
          ->to($user->getEmail())
          ->subject('Welcome!')
          ->htmlTemplate('emails/welcome.html.twig')
          ->context(['name' => $user->getName()]);
      

Integration Tips

  • Custom Twig Extensions: Create a service tagged as twig.extension:

    # config/services.yaml
    services:
        App\Twig\AppExtension:
            tags: ['twig.extension']
    
    // src/Twig/AppExtension.php
    class AppExtension extends AbstractExtension
    {
        public function getFunctions(): array
        {
            return [
                new Function('app_greet', [AppRuntime::class, 'greet']),
            ];
        }
    }
    
  • Debugging: Enable Twig’s debug mode in config/packages/dev/twig.yaml:

    twig:
        debug: true
        strict_variables: true
    
  • Caching: Configure runtime caching for production:

    twig:
        cache: '%kernel.cache_dir%/twig'
    

Gotchas and Tips

Pitfalls

  1. Caching Quirks:

    • Block Prefixes: Nested loops with {% block %} can leak prefixes. Use unique names:
      {% block user_row_%index% %}
      
    • Clear Cache: After modifying Twig templates, clear the cache:
      php bin/console cache:clear
      
  2. Form Theming:

    • Bootstrap Layouts: Ensure form errors are outside <label> tags for Bootstrap 4/5 compatibility:
      {# templates/forms/bootstrap_4_layout.html.twig #}
      {% block form_errors %}
          <div class="invalid-feedback">{{ form_errors|join(', ') }}</div>
      {% endblock %}
      
    • Button Labels: Explicitly disable labels with label: false in form options:
      $builder->add('submit', SubmitType::class, ['label' => false]);
      
  3. Security:

    • XSS in fileExcerpt(): Sanitize file paths passed to {{ fileExcerpt(path) }} (fixed in v8.1.0+).
    • Access Control: Use is_granted() sparingly in loops; prefer server-side checks for performance.
  4. Dependency Conflicts:

    • phpdocumentor/reflection-docblock: Ensure compatibility with version ^6.0 (fixed in v8.0.5+).
    • Twig Version: Requires Twig ^3.25 (check composer.json constraints).

Debugging Tips

  • Template Not Found: Verify the templates/ directory is in the kernel.project_dir (default: var/cache/dev/).
  • Service Unavailable: Ensure twig service is autowired or manually configured in services.yaml.
  • Runtime Errors: Enable strict_variables in dev to catch undefined variables early.

Extension Points

  1. Custom Globals: Add globals via a compiler pass or event subscriber:

    services:
        App\EventSubscriber\TwigGlobalSubscriber:
            tags: ['kernel.event_subscriber']
    
    class TwigGlobalSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents(): array
        {
            return [KernelEvents::REQUEST => 'onKernelRequest'];
        }
    
        public function onKernelRequest(RequestEvent $event): void
        {
            $twig = $event->getKernel()->getContainer()->get('twig');
            $twig->addGlobal('app_config', $this->getAppConfig());
        }
    }
    
  2. Override Twig Environment: Replace the default environment in a bundle:

    // src/DependencyInjection/AppExtension.php
    public function load(array $configs, ContainerBuilder $container): void
    {
        $container->set('twig', $this->createTwigEnvironment($container));
    }
    
  3. CLI Templates: Use Twig for CLI output by injecting the twig service into commands:

    class MyCommand extends Command
    {
        public function __construct(private TwigEngine $twig)
        {
            parent::__construct();
        }
    
        protected function execute(InputInterface $input, OutputInterface $output): int
        {
            $output->writeln($this->twig->render('cli/output.html.twig', []));
            return Command::SUCCESS;
        }
    }
    

Pro Tips

  • Reusable Components: Use Twig’s {% include %} and {% embed %} for modular templates.
  • Asset Versioning: Auto-version assets to bust caches:
    <link rel="stylesheet" href="{{ asset('css/style.css', 'unique123') }}">
    
  • Form Component: Leverage Symfony’s form component for complex UIs without reinventing the wheel.
  • Translation: Use Twig’s trans filter for dynamic content:
    {{ 'Welcome, %name%'|trans({'%name%': user.name }) }}
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope