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

Decorator Bundle Laravel Package

cleentfaar/decorator-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer:
    composer require cleentfaar/decorator-bundle
    
  2. Enable the Bundle in config/bundles.php:
    return [
        // ...
        Cleentfaar\DecoratorBundle\CLDecoratorBundle::class => ['all' => true],
    ];
    
  3. Register Decorators in services.yaml:
    services:
        App\Decorator\MyDecorator:
            decorates: App\Service\MyService
            arguments: ['@App\Decorator\MyDecorator.inner']
    

First Use Case: Decorating a Service

Decorate a Symfony service (e.g., UserService) to add logging or caching:

// src/Decorator/UserDecorator.php
namespace App\Decorator;

use App\Service\UserServiceInterface;
use Psr\Log\LoggerInterface;

class UserDecorator implements UserServiceInterface
{
    private $decorated;
    private $logger;

    public function __construct(UserServiceInterface $decorated, LoggerInterface $logger)
    {
        $this->decorated = $decorated;
        $this->logger = $logger;
    }

    public function findUser($id)
    {
        $this->logger->info('Fetching user', ['id' => $id]);
        return $this->decorated->findUser($id);
    }
}

Twig Integration (Optional)

Enable Twig extensions in config/packages/twig.yaml:

twig:
    extensions:
        - Cleentfaar\DecoratorBundle\Twig\DecoratorExtension

Use in templates:

{{ user|decorate('App\Decorator\UserDecorator') }}

Implementation Patterns

Dependency Injection Workflow

  1. Decorate Existing Services: Use the decorates tag in services.yaml to wrap services with decorators.

    services:
        App\Service\MyService:
            class: App\Service\MyService
        App\Decorator\MyDecorator:
            decorates: App\Service\MyService
            arguments: ['@App\Decorator\MyDecorator.inner']
    
    • Pro Tip: Chain decorators by nesting them (e.g., CacheDecorator wrapping a LoggerDecorator).
  2. Dynamic Decoration: For runtime decoration (e.g., based on user roles), use the DecoratorFactory:

    $decorator = $container->get('decorator.factory')->decorate(
        $originalService,
        'App\Decorator\DynamicDecorator',
        ['param1' => 'value']
    );
    

Twig Integration Patterns

  1. Decorate Objects in Templates: Use the decorate Twig filter to apply decorators dynamically:

    {% set decoratedUser = user|decorate('App\Decorator\UserDecorator') %}
    {{ decoratedUser.getFormattedName() }}
    
  2. Pass Decorator Parameters:

    {{ user|decorate('App\Decorator\UserDecorator', {'format': 'full'}) }}
    

Common Use Cases

  1. Logging: Decorate services to log method calls without modifying original logic.

    public function someMethod()
    {
        $this->logger->debug('Calling someMethod');
        return $this->decorated->someMethod();
    }
    
  2. Caching: Wrap expensive operations with a caching decorator.

    public function fetchData()
    {
        return $this->cache->get('data_key', function() {
            return $this->decorated->fetchData();
        });
    }
    
  3. Validation: Add validation logic around existing methods.

    public function update($data)
    {
        if (!$this->validator->isValid($data)) {
            throw new \InvalidArgumentException('Invalid data');
        }
        return $this->decorated->update($data);
    }
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies: Avoid decorating a service that is itself a dependency of the decorator.

    • Fix: Use constructor injection carefully or refactor dependencies.
  2. Twig Filter Scope: The decorate Twig filter operates on the current object scope. If the object isn’t passed correctly, the decorator won’t work.

    • Fix: Ensure the object is properly instantiated before passing to Twig.
  3. Outdated Package: Last updated in 2014, so:

    • Test thoroughly with Symfony 5+/Laravel (if using via bridge).
    • Some DI features (e.g., autoconfigure) may not work as expected.
    • Workaround: Manually configure services in services.yaml.
  4. Decorator Naming Conflicts: If two decorators implement the same interface, Symfony may fail to autowire.

    • Fix: Use fully qualified class names in decorates or arguments.

Debugging Tips

  1. Check Decorator Chain: Use dump($service) to inspect the decorated object’s class hierarchy.

    $service = $container->get('App\Service\MyService');
    dump(get_class($service)); // Should show the decorator class
    
  2. Twig Debugging: If decorate fails silently, enable Twig strict mode:

    twig:
        strict_variables: true
    
  3. Service Dump: List all services to verify decoration:

    php bin/console debug:container | grep MyService
    

Extension Points

  1. Custom Decorator Factory: Extend DecoratorFactory to support dynamic decorator resolution:

    class CustomDecoratorFactory extends \Cleentfaar\DecoratorBundle\Decorator\DecoratorFactory
    {
        public function resolveDecorator($original, $decoratorClass, array $args = [])
        {
            // Custom logic here
            return parent::resolveDecorator($original, $decoratorClass, $args);
        }
    }
    

    Register it in services.yaml:

    services:
        decorator.factory:
            class: App\Decorator\CustomDecoratorFactory
            decorates: cleentfaar_decorator.decorator_factory
    
  2. Twig Extension Overrides: Override the Twig extension to add custom filters:

    class CustomDecoratorExtension extends \Cleentfaar\DecoratorBundle\Twig\DecoratorExtension
    {
        public function getFilters()
        {
            return array_merge(parent::getFilters(), [
                new \Twig\TwigFilter('custom_decorate', [$this, 'customDecorate']),
            ]);
        }
    }
    

    Register it:

    twig:
        extensions:
            - App\Twig\CustomDecoratorExtension
    

Laravel-Specific Notes

  • Service Provider Integration: If using in Laravel, bind the bundle’s services in a provider:

    public function register()
    {
        $this->app->register(new \Cleentfaar\DecoratorBundle\CLDecoratorBundle());
        $this->app->bind('decorator.factory', function($app) {
            return new \Cleentfaar\DecoratorBundle\Decorator\DecoratorFactory();
        });
    }
    
  • Facade Support: Decorate facades by binding the decorated service:

    Facade::bind('MyService', function($app) {
        return $app->make('App\Decorator\MyDecorator');
    });
    
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.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver