Home > Back-end >  Using decoration stack to decorate an existing service?
Using decoration stack to decorate an existing service?

Time:12-06

Symfony docs show a very neat way to create a stack of decorators:

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return function(ContainerConfigurator $container) {
    $container>stack('decorated_foo_stack', [
            inline_service(\Baz::class),
            inline_service(\Bar::class),
            inline_service(\Foo::class),
        ])
    ;
};

And show this as an alternative to doing:

// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return function(ContainerConfigurator $configurator) {
    $services = $configurator->services();

    $services->set(\Foo::class);

    $services->set(\Bar::class)
        ->decorate(\Foo::class, null, 5)
        ->args([service('.inner')]);

    $services->set(\Baz::class)
        ->decorate(\Foo::class, null, 1)
        ->args([service('.inner')]);
};

Problem is, the "neater" approach leaves service Foo::class undecorated. Applications that use the original definition do not go through the stack, but access the original service.

In my case, I have to decorate a service called api_platform.serializer.context_builder. Doing this works in creating a decorated stack:

$services->stack(
    'decorated_context_builder',
    [
        inline_service(SupportTicketMessageContextBuilder::class),
        inline_service(LeadContextBuilder::class),
        inline_service(BidContextBuilder::class),
        inline_service(PartnerContextBuilder::class),
        inline_service(WebProfileContextBuilder::class),
        service('api_platform.serializer.context_builder'),
    ]
);

The service is provided by a vendor dependency, and it's used by that dependency. When it uses the injected api_platform.serializer.context_builder it completely ignores my newly created decorated_context_builder stack.

Instead, if I create the stack manually:

    $services->set(LeadContextBuilder::class)
        ->decorate('api_platform.serializer.context_builder', priority: 4)
    ;

    $services->set(BidContextBuilder::class)
        ->decorate('api_platform.serializer.context_builder', priority: 3)
    ;

// etc, etc, etc

... it works as expected.

How can I use a decoration stack to decorate an existing service definition, so that the existing definition gets decorated?

CodePudding user response:

Apparently this is not possible with stacking decorators, as they are not currently compatible with decorating other services, just to create stand-alone stacks.

  • Related