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

spiral/twig-bridge

Twig adapter for the Spiral Framework. Adds a Twig view engine via TwigBootloader, with support for custom extensions, options, and processors. Configure eagerly through TwigEngine or lazily through TwigBootloader. Requires spiral/views.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require spiral/twig-bridge
    

    Register the TwigBridge service provider in config/app.php under providers:

    Spiral\TwigBridge\TwigBridgeServiceProvider::class,
    
  2. Basic Configuration Publish the default config (optional):

    php artisan vendor:publish --provider="Spiral\TwigBridge\TwigBridgeServiceProvider" --tag="config"
    

    Configure paths in config/twig-bridge.php:

    'paths' => [
        'templates' => resource_path('views'),
        'cache'     => storage_path('framework/views'),
    ],
    
  3. First Use Case: Rendering a Template Inject the TwigBridge into a controller or service:

    use Spiral\TwigBridge\TwigBridgeInterface;
    
    class HomeController
    {
        public function __construct(private TwigBridgeInterface $twig)
        {
        }
    
        public function index()
        {
            return $this->twig->render('home.index.twig', [
                'title' => 'Welcome',
            ]);
        }
    }
    

Implementation Patterns

Common Workflows

  1. Template Rendering

    • Basic Rendering: Use render() to output templates directly:
      $html = $this->twig->render('email.welcome.twig', ['user' => $user]);
      
    • Streaming: For large templates, use renderStream() to avoid memory issues:
      $this->twig->renderStream('report.large.twig', $data);
      
  2. Reusable Components

    • Embedding: Include partials or components:
      {% embed 'layouts/base.twig' %}
          {{ block('content') }}
      {% endembed %}
      
    • Macros: Define reusable snippets in Twig:
      {% macro alert(type, message) %}
          <div class="alert alert-{{ type }}">{{ message }}</div>
      {% endmacro %}
      
  3. Integration with Laravel

    • Blade Compatibility: Use Twig alongside Blade by configuring paths:
      'paths' => [
          'templates' => [resource_path('views/twig'), resource_path('views/blade')],
      ],
      
    • Middleware: Pass Twig environment to middleware for dynamic templates:
      public function handle($request, Closure $next)
      {
          $request->twig = $this->twig;
          return $next($request);
      }
      
  4. Dynamic Template Selection

    • Use runtime logic to select templates:
      $template = $user->prefersDarkMode() ? 'dark.layout.twig' : 'light.layout.twig';
      return $this->twig->render($template, $data);
      
  5. Testing

    • Mock TwigBridgeInterface in tests:
      $this->mock(TwigBridgeInterface::class)->shouldReceive('render')->once()->andReturn('<html>...</html>');
      

Integration Tips

  1. Caching

    • Enable Twig cache for production:
      'cache' => [
          'enabled' => env('APP_ENV') === 'production',
      ],
      
    • Clear cache manually:
      php artisan twig:clear-cache
      
  2. Extensions

    • Register custom Twig extensions:
      $this->twig->getEnvironment()->addExtension(new \Your\CustomExtension());
      
  3. Error Handling

    • Configure Twig error handling in config/twig-bridge.php:
      'debug' => env('APP_DEBUG', false),
      
  4. Asset Management

    • Use Twig’s asset() function (if integrated with Laravel Mix/Vite):
      <link rel="stylesheet" href="{{ asset('css/app.css') }}">
      

Gotchas and Tips

Pitfalls

  1. Path Configuration

    • Ensure templates and cache paths are writable:
      chmod -R 775 storage/framework/views
      
    • Gotcha: Forgetting to publish config may lead to default paths not matching your project structure.
  2. Namespace Conflicts

    • Twig templates use twig namespace by default. Avoid naming conflicts with Laravel’s Blade directives:
      {# Not @if, but {% if %} #}
      
  3. Caching Quirks

    • Gotcha: Disabling cache in development may slow down template rendering significantly.
    • Clear cache after template changes:
      php artisan twig:clear-cache
      
  4. Dependency Injection

    • Gotcha: Forgetting to inject TwigBridgeInterface will throw BindingResolutionException.
    • Prefer constructor injection over service locator:
      // Avoid:
      $this->twig = app(TwigBridgeInterface::class);
      
  5. Twig vs. Blade Syntax

    • Gotcha: Mixing Twig and Blade syntax in the same template can cause parsing errors.
    • Example of conflicting syntax:
      {# Twig: {% if %} #}
      @if(true) {# Blade: @if #}
          {{-- This will fail --}}
      @endif
      

Debugging Tips

  1. Enable Debug Mode Set debug: true in config/twig-bridge.php to get detailed error messages.

  2. Template Not Found

    • Verify the template path is correct (case-sensitive on Linux).
    • Check paths.templates in config and ensure the file exists.
  3. Variable Errors

    • Twig is strict about undefined variables. Use {{ variable|default('fallback') }} to avoid errors.
  4. Performance Issues

    • Profile Twig rendering with twig:profile command (if available).
    • Optimize templates by avoiding deep nesting and excessive filters.
  5. Extension Conflicts

    • Disable extensions one by one to isolate conflicts:
      $env->removeExtension($extension);
      

Extension Points

  1. Custom Filters Add a filter to Twig:

    $this->twig->getEnvironment()->addFilter(new \Twig\TwigFilter('custom_filter', function ($value) {
        return strtoupper($value);
    }));
    
  2. Global Variables Pass data to all templates:

    $this->twig->getEnvironment()->addGlobal('app_name', config('app.name'));
    
  3. Custom Functions Register a Twig function:

    $this->twig->getEnvironment()->addFunction(new \Twig\TwigFunction('greet', function ($name) {
        return "Hello, $name!";
    }));
    
  4. Event Listeners Listen to Twig events (e.g., Twig\SourceContextLoadedEvent):

    $this->twig->getEnvironment()->addEventListener(\Twig\SourceContextLoadedEvent::class, function ($event) {
        // Log template paths
    });
    
  5. Override Default Environment For advanced use cases, bind a custom Twig\Environment:

    $this->app->bind(TwigBridgeInterface::class, function ($app) {
        $loader = new \Twig\Loader\FilesystemLoader($app['config']['twig-bridge.paths.templates']);
        $env = new \Twig\Environment($loader, [
            'cache' => $app['config']['twig-bridge.paths.cache'],
        ]);
        return new TwigBridge($env);
    });
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky