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 Bundle Laravel Package

symfony/twig-bundle

TwigBundle integrates Twig templating into the Symfony full-stack framework, providing seamless configuration and services for rendering templates. Includes links for contributing, reporting issues, and submitting pull requests via the main Symfony repository.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require symfony/twig-bundle
    

    The bundle auto-registers when Symfony Flex detects it. No manual bundles.php entry is needed in Symfony 5+.

  2. First Use Case: Create a template in templates/base.html.twig:

    <!DOCTYPE html>
    <html>
        <head>
            <title>{% block title %}Welcome!{% endblock %}</title>
        </head>
        <body>
            {% block body %}{% endblock %}
        </body>
    </html>
    

    Extend it in templates/index.html.twig:

    {% extends 'base.html.twig' %}
    
    {% block body %}
        <h1>Hello, {{ name }}!</h1>
    {% endblock %}
    
  3. Render in Controller:

    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    
    class HomeController extends AbstractController
    {
        #[Route('/')]
        public function index(): Response
        {
            return $this->render('index.html.twig', [
                'name' => 'World',
            ]);
        }
    }
    
  4. Verify: Run php bin/console server:run and visit /. Twig auto-reloads during development.

Key Configuration

Check config/packages/twig.yaml for defaults:

twig:
    default_path: '%kernel.project_dir%/templates'
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    auto_reload: '%kernel.debug%'
    cache: '%kernel.cache_dir%/twig'

Where to Look First

  • Symfony Docs: Twig Integration
  • Template Paths: var/cache/dev/twig/ (development) or var/cache/prod/twig/ (production)
  • Globals: Define in config/packages/twig.yaml under globals.

Implementation Patterns

Core Workflows

  1. Template Inheritance & Blocks:

    • Use {% extends %} and {% block %} for reusable layouts.
    • Example: Base template with {% block stylesheets %}{% endblock %} for child templates to override.
  2. Macros for Reusable Components:

    {# templates/_components/alert.html.twig #}
    {% macro alert(type, message) %}
        <div class="alert alert-{{ type }}">
            {{ message }}
        </div>
    {% endmacro %}
    

    Include in templates:

    {% import '_components/alert.html.twig' as alert %}
    {{ alert.alert('success', 'Operation completed!') }}
    
  3. Dynamic Content with Embeds:

    {% embed '_partials/header.html.twig' %}
        {% block title %}Custom Title{% endblock %}
    {% endembed %}
    
  4. Form Integration:

    {{ form_start(form) }}
        {{ form_row(form.name) }}
        {{ form_row(form.email) }}
    {{ form_end(form) }}
    

    Auto-generates HTML with CSRF protection and validation errors.

  5. Asset Management:

    <link rel="stylesheet" href="{{ asset('css/app.css') }}">
    

    Uses Symfony’s asset() function for versioned URLs.


Integration Tips

  1. Custom Twig Extensions: Create a service with #[AsTwigExtension]:

    use Symfony\Component\DependencyInjection\Attribute\AsTwigExtension;
    use Twig\Extension\AbstractExtension;
    use Twig\TwigFunction;
    
    #[AsTwigExtension]
    class MyTwigExtension extends AbstractExtension
    {
        public function getFunctions(): array
        {
            return [
                new TwigFunction('greet', [$this, 'greetUser']),
            ];
        }
    
        public function greetUser(string $name): string
        {
            return "Hello, $name!";
        }
    }
    

    Use in templates: {{ greet('Alice') }}.

  2. Filters and Tests:

    #[AsTwigFilter(name: 'uppercase_first')]
    public function uppercaseFirst(string $string): string
    {
        return ucfirst(strtolower($string));
    }
    
    #[AsTwigTest]
    public function isEven(int $number): bool
    {
        return $number % 2 === 0;
    }
    

    Usage: {{ 'hello'|uppercase_first }} or {% if 4 is even %}...{% endif %}.

  3. Event-Driven Templating: Listen to TwigTemplateEvent to modify templates dynamically:

    use Symfony\Component\HttpKernel\Event\ViewEvent;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
    
    #[AsEventListener(event: KernelEvents::VIEW, method: 'onKernelView')]
    public function onKernelView(ViewEvent $event): void
    {
        if (!$event->getController() instanceof Controller) {
            return;
        }
    
        $template = $event->getController()[1];
        if (str_contains($template, 'index.html.twig')) {
            $event->getController()[1] = 'custom_template.html.twig';
        }
    }
    
  4. Caching Strategies:

    • Development: auto_reload: true (default).
    • Production: Enable cache: true and set cache_dir to var/cache/prod/twig.
    • Preload Templates: Use kernel.build_dir for templates known at compile time (Symfony 7.3+):
      twig:
          preload: true
      
  5. Security Context:

    • Enable strict_variables: true in development to catch undefined variables.
    • Use {{ app.user|json_encode|raw }} to pass data safely to JavaScript.

Advanced Patterns

  1. Bundle-Specific Templates: Place templates in src/MyBundle/Resources/views/ and reference them with @MyBundle/views/template.html.twig.

  2. Environment-Specific Templates: Use config/packages/dev/twig.yaml to override settings per environment.

  3. Twig in CLI Commands:

    use Symfony\Component\HttpKernel\KernelInterface;
    use Twig\Environment;
    
    public function __construct(
        private KernelInterface $kernel,
        private Environment $twig
    ) {}
    
    public function execute(): void
    {
        $html = $this->twig->render('emails/welcome.html.twig', [
            'name' => 'User',
        ]);
        // Send email...
    }
    

    Register Twig\Environment as a service in config/services.yaml.

  4. Testing Templates: Use Twig\Test\IntegrationTestCase or mock the Twig\Environment:

    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    
    class MyTest extends WebTestCase
    {
        public function testTemplateRendering()
        {
            $client = static::createClient();
            $client->request('GET', '/');
            $this->assertSelectorTextContains('h1', 'Hello, World!');
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Template Not Found Errors:

    • Cause: Incorrect path or missing default_path in twig.yaml.
    • Fix: Verify paths are relative to templates/ or use @Bundle/views/.
    • Debug: Run php bin/console debug:container twig to check paths.
  2. Caching Issues:

    • Cause: Stale cache in production after template changes.
    • Fix: Clear cache (php bin/console cache:clear) or use auto_reload: true in dev.
    • Tip: For Symfony 7.3+, use twig.preload: true to compile templates at build time.
  3. Undefined Variables:

    • Cause: strict_variables: false (default in prod) hides errors.
    • Fix: Enable strict_variables: true in dev or use {{ dump(var) }} to debug.
  4. Asset Versioning:

    • Cause: Hardcoded asset paths (e.g., /css/app.css) break caching.
    • Fix: Always use {{ asset('css/app.css') }} for versioned URLs.
  5. Macro Scope:

    • Cause: Macros defined in one template are not available in another.
    • Fix: Use {% import '_macros.html.twig' as macros %} to share macros across templates.
  6. CSRF Token Mismatch:

    • Cause: Using form_start() without a form instance or in non-GET requests.
    • Fix: Pass the form object: {{ form_start(form) }}.
  7. Twig vs. PHP Logic:

    • Gotcha: Overusing Twig for complex logic (e.g., loops with 1000+ items).
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport