Skip to content

[DependencyInjection] Add new attributes to allow inlined services while using autowiring #52819

Closed
@DaDeather

Description

@DaDeather

Description

Currently when using autowiring and declaring service configuration on class level it's (as far as I know) not possible to define a inlined service or define a factory that may create an instance of the service with custom parameters.

So let's take a look at this:

class SomeSourceAwareLogger
{
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly string $someSource,
    ) {
    }
}

class SomeClass
{
    public function __construct(
        private readonly SomeSourceAwareLogger $logger,
    ) {
    }
}

This would currently lead to an error when trying to build an instance of SomeClass since SomeSourceAwareLogger::$someSource is a string parameter that the autowiring can not resolve.

So for this to work one would either have to
a) add an #[Autowire] attribute to SomeSourceAwareLogger::$someSource and would have to create multiple classes for every source
b) configure one or multiple instances of SomeSourceAwareLogger in the config files with different sources and then configure SomeClass::logger as well

This would then look like this:

class SomeSourceAwareLogger1
{
    public function __construct(
        private readonly LoggerInterface $logger,
        #[Autowire(param: 'someSource1')]
        private readonly string $someSource,
    ) {
    }
}

class SomeSourceAwareLogger2
{
    public function __construct(
        private readonly LoggerInterface $logger,
        #[Autowire(param: 'someSource2')]
        private readonly string $someSource,
    ) {
    }
}

class SomeClass
{
    public function __construct(
        private readonly SomeSourceAwareLogger1 $logger1,
        private readonly SomeSourceAwareLogger2 $logger2,
    ) {
    }
}

// OR
class SomeSourceAwareLogger
{
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly string $someSource,
    ) {
    }
}

class SomeClass
{
    public function __construct(
        #[Autowire(service: 'someSourceAwareLogger1')]
        private readonly SomeSourceAwareLogger $logger1,
        #[Autowire(service: 'someSourceAwareLogger2')]
        private readonly SomeSourceAwareLogger $logger2,
    ) {
    }
}

// In services.yaml or wherever:
// services:
//    someSourceAwareLogger1:
//        class: SomeSourceAwareLogger
//        arguments:
//            - '@LoggerInterface'
//            - 'someSource1'
//
//    someSourceAwareLogger2:
//        class: SomeSourceAwareLogger
//        arguments:
//            - '@LoggerInterface'
//            - 'someSource2'

What I'd like to introduce is having it just at a single point by saying something like:

class SomeSourceAwareLogger
{
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly string $someSource,
    ) {
    }
}

// And then just either:

class SomeClass
{
    public function __construct(
        #[InlineService(class: SomeSourceAwareLogger::class, params: [new Reference(LoggerInterface::class), self::class])]
        private readonly SomeSourceAwareLogger $logger,
    ) {
    }
}

// OR

class SomeClass
{
    public function __construct(
        #[InlineFactory(service: SomeSourceAwareLoggerFactory::class, params: [self::class])]
        private readonly SomeSourceAwareLogger $logger,
    ) {
    }
}

Example

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions