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

Content Injector Bundle Laravel Package

cethyworks/content-injector-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require cethyworks/content-injector-bundle
    

    Register the bundle in AppKernel.php (or config/bundles.php for Symfony 4+):

    new Cethyworks\ContentInjectorBundle\CethyworksContentInjectorBundle(),
    
  2. First Injection: Inject a simple string into all responses:

    $subscriber = $container->get('cethyworks_content_injector.subscriber');
    $subscriber->registerCommand(function() { return '<script>console.log("Hello!");</script>'; });
    

    Verify: Check the rendered page source to confirm the injected content appears.

First Use Case

Inject a footer script dynamically:

$subscriber->registerCommand(function() {
    return '<script src="/dynamic-footer.js?v=' . time() . '"></script>';
});

Trigger: Visit any route—script appears in the response.


Implementation Patterns

Core Workflow

  1. Register Commands:

    • Simple Strings: Use registerCommand(callable) for static content.
    • Dynamic Logic: Pass a closure with access to the Request or Response via dependency injection.
      $subscriber->registerCommand(function($request) {
          return $request->get('debug') ? '<!-- DEBUG MODE -->' : '';
      });
      
    • Twig Templates: Use TwigCommandHandler for dynamic templates.
      $handler = $container->get('cethyworks_content_injector.twig_command_handler');
      $handler->registerCommand('@App/Resources/views/inject/footer.html.twig', ['user' => $user]);
      
  2. Form Integration: Extend FormType to inject form-specific content:

    $builder->add('field', TextType::class, [
        'injector' => [
            'command' => function($formView) {
                return '<div class="form-hint">' . $formView->children['field']->vars['label'] . '</div>';
            }
        ]
    ]);
    
  3. Conditional Injection: Filter commands by route, HTTP method, or user role:

    $subscriber->registerCommand(function($request) {
        return $request->get('_route') === 'dashboard' ? '<div class="dashboard-only">...</div>' : '';
    });
    

Integration Tips

  • Symfony Events: Hook into kernel.response to inspect/modify injected content:
    $dispatcher->addListener('kernel.response', function($event) {
        $response = $event->getResponse();
        if ($response->headers->contains('X-Injected')) {
            // Custom logic for injected responses
        }
    });
    
  • Asset Management: Combine with AssetMapper for versioned injected assets:
    $subscriber->registerCommand(function() {
        return $this->get('asset_mapper')->getUrl('js/injector.js');
    });
    
  • Performance: Cache compiled Twig templates if commands are static:
    $handler->registerCommand('@App/Resources/views/cacheable.html.twig', [], ['cache_key' => 'footer_v1']);
    

Gotchas and Tips

Pitfalls

  1. Event Timing:

    • Commands run after the response is generated but before it’s sent. Avoid injecting into responses that are already modified (e.g., by HttpCache).
    • Debugging: Check if kernel.response fires too early by logging $event->getResponse()->getContent().
  2. Twig Autoloading:

    • Ensure Twig templates are in a bundle’s Resources/views directory or configure custom paths in twig.form.templates (Symfony 3) or twig.path (Symfony 4+).
    • Error: TemplateNotFoundException → Verify template paths and bundle compilation.
  3. FormType Extension:

    • The injector option only works with FormType (not CollectionType or FormInterface directly). Use FormEvents::PRE_SET_DATA to attach to nested forms:
      $builder->addEventListener(FormEvents::PRE_SET_DATA, function($event) {
          $event->getForm()->add('sub_form', SubFormType::class, ['injector' => [...]]);
      });
      
  4. Command Order:

    • Commands are executed in registration order. Use priorities (if supported) or wrap commands in closures to enforce order:
      $subscriber->registerCommand(function() { return '<head>'; });
      $subscriber->registerCommand(function() { return '<body>'; }, 10); // Lower priority = later execution
      

Debugging

  • Inspect Injected Content: Override the subscriber to log commands:
    $subscriber = $container->get('cethyworks_content_injector.subscriber');
    $subscriber->registerCommand(function() {
        return '<!-- INJECTED: ' . microtime(true) . ' -->';
    });
    
  • Disable Injection: Temporarily remove the bundle from AppKernel.php to isolate issues.

Extension Points

  1. Custom Command Handlers: Extend CommandHandlerInterface to support new injection types (e.g., JSON APIs):

    class JsonCommandHandler implements CommandHandlerInterface {
        public function handle($command, $request, $response) {
            if ($response->headers->contains('Content-Type', 'application/json')) {
                $response->setContent(json_encode(['injected' => $command]));
            }
        }
    }
    

    Register via dependency injection.

  2. Response Modifiers: Hook into kernel.response to transform injected content:

    $dispatcher->addListener('kernel.response', function($event) {
        $response = $event->getResponse();
        $content = $response->getContent();
        $content = preg_replace('/<!-- INJECTED_START -->(.*)<!-- INJECTED_END -->/s', '$1', $content);
        $response->setContent($content);
    });
    
  3. Configuration: Override default behavior via config/packages/cethyworks_content_injector.yaml:

    cethyworks_content_injector:
        enabled: true # Disable globally
        twig:
            debug: false # Disable Twig debug for injected templates
    

Pro Tips

  • A/B Testing: Use commands to inject dynamic CSS/JS based on user segments:
    $subscriber->registerCommand(function($request) {
        return $request->get('variant') === 'A' ? '<link rel="stylesheet" href="/a.css">' : '<link rel="stylesheet" href="/b.css">';
    });
    
  • Analytics: Track injections via data-* attributes:
    $subscriber->registerCommand(function() {
        return '<div data-injected="footer" data-timestamp="' . time() . '">...</div>';
    });
    
  • Security: Sanitize injected content to prevent XSS:
    $subscriber->registerCommand(function($command) {
        return $this->get('twig')->escapeFilter($command);
    });
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware