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

Render Service Twig Extension Bundle Laravel Package

danilovl/render-service-twig-extension-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require danilovl/render-service-twig-extension-bundle
    

    Add to config/bundles.php (Symfony) or config/app.php (Laravel via Symfony bridge):

    return [
        // ...
        Danilovl\RenderServiceTwigExtensionBundle\RenderServiceTwigExtensionBundle::class => ['all' => true],
    ];
    
  2. First Use Case Define a service with a method to render:

    // src/Service/RenderableService.php
    namespace App\Service;
    
    class RenderableService {
        public function renderPartial(string $template, array $data = []): string {
            return \Twig\Environment::createLoader(...)->render($template, $data);
        }
    }
    

    Register it as a service (Symfony/Laravel):

    # config/services.yaml
    services:
        App\Service\RenderableService: ~
    

    Use in Twig:

    {{ render_service('App\Service\RenderableService', 'renderPartial', ['template': 'partials/_card.html.twig', 'data': {'title': 'Hello'}]) }}
    

Implementation Patterns

Common Workflows

  1. Replacing render(controller())

    • Before: {{ render(controller('App\Controller\CardController::showCardAction')) }}
    • After: Define a service method to return a rendered string:
      public function renderCard(array $data): string {
          return $this->twig->render('card.html.twig', $data);
      }
      
      Use in Twig:
      {{ render_service('App\Service\CardService', 'renderCard', {'data': {'title': 'Card'}}) }}
      
  2. Dynamic Service Resolution Use dependency injection to pass services dynamically:

    {% set service = service('App\Service\DynamicRenderer') %}
    {{ render_service(service, 'render', ['template': 'dynamic.html.twig']) }}
    
  3. Integration with Laravel

    • Bind the bundle via Symfony bridge (if using laravel/symfony):
      // config/app.php
      'extra' => [
          'bundles' => [
              Danilovl\RenderServiceTwigExtensionBundle\RenderServiceTwigExtensionBundle::class => ['all' => true],
          ],
      ];
      
    • Use in Blade (via Twig):
      @php
          $rendered = \Twig\Environment::createLoader(...)->render(
              'partials/_sidebar.blade.twig',
              ['user' => $user]
          );
      @endphp
      {!! $rendered !!}
      
      Or create a custom Twig extension in Laravel:
      // app/Providers/AppServiceProvider.php
      public function boot() {
          $twig = app('view.factory')->getEngine();
          $twig->addExtension(new \Danilovl\RenderServiceTwigExtensionBundle\Twig\RenderServiceExtension());
      }
      
  4. Caching Rendered Output Cache service method results to avoid redundant rendering:

    public function renderCached(string $template, array $data, string $cacheKey): string {
        return Cache::remember($cacheKey, 3600, function() use ($template, $data) {
            return $this->twig->render($template, $data);
        });
    }
    

Gotchas and Tips

Pitfalls

  1. Service Autowiring

    • Ensure services are properly autowired. If using Laravel, manually bind services to the container:
      $this->app->bind('App\Service\RenderableService', function ($app) {
          return new RenderableService($app['twig']);
      });
      
  2. Circular Dependencies

    • Avoid circular calls between services and Twig templates. Example:
      {{ render_service('A', 'render', {'data': render_service('B', 'render', {})}) }}  <!-- Risky -->
      
      Pre-render data in PHP before passing to Twig.
  3. Performance Overhead

    • While faster than render(controller()), excessive use of render_service can still impact performance. Benchmark critical paths.
  4. Twig Environment Configuration

    • Ensure the Twig environment used in services matches the one in your templates (loaders, extensions, etc.).

Debugging

  1. Service Not Found

    • Verify the service is registered in the container:
      php bin/console debug:container App\Service\RenderableService
      
    • For Laravel, check bindings:
      php artisan container:list | grep RenderableService
      
  2. Method Not Callable

    • Confirm the method exists and is public:
      public function renderPartial() { ... }  // Must be public
      
  3. Template Loading Issues

    • Use absolute paths in templates (e.g., '@App/partials/_card.html.twig') to avoid loader conflicts.

Extension Points

  1. Customizing the Twig Extension Override the default extension in Symfony:

    # config/packages/danilovl_render_service_twig_extension.yaml
    danilovl_render_service_twig_extension:
        extension_class: App\Twig\CustomRenderServiceExtension
    

    Or in Laravel:

    $twig->addExtension(new CustomRenderServiceExtension());
    
  2. Adding Validation Extend the bundle to validate service/method/data before rendering:

    class ValidatingRenderServiceExtension extends RenderServiceExtension {
        public function renderService(ServiceInterface $service, string $method, array $arguments) {
            if (!$this->isValidService($service)) {
                throw new \RuntimeException('Invalid service');
            }
            return parent::renderService($service, $method, $arguments);
        }
    }
    
  3. Laravel-Specific Tips

    • Use view()->make() for partials and cache them:
      public function renderPartial(string $view, array $data = []): string {
          return Cache::remember("view_{$view}", 3600, function() use ($view, $data) {
              return view($view, $data)->render();
          });
      }
      
    • Integrate with Laravel Mix/Purifier for asset/template security:
      use Purifier;
      return Purifier::clean($this->twig->render($template, $data));
      
  4. Security

    • Sanitize user-provided template names/methods to prevent arbitrary code execution:
      if (!preg_match('/^[a-zA-Z0-9_]+$/', $method)) {
          throw new \InvalidArgumentException('Invalid method 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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony