Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DaDeather opened this issue Nov 30, 2023 · 0 comments · Fixed by #52820
Closed

Comments

@DaDeather
Copy link
Contributor

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

DaDeather added a commit to DaDeather/symfony that referenced this issue Nov 30, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Nov 30, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Nov 30, 2023
…ry attributes to allow service configuration on class level
@xabbuh xabbuh added the Feature label Nov 30, 2023
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…ry attributes to allow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…llow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…llow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…llow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Dec 1, 2023
…llow service configuration on class level
nicolas-grekas pushed a commit to DaDeather/symfony that referenced this issue Dec 27, 2023
DaDeather added a commit to DaDeather/symfony that referenced this issue Jan 3, 2024
…llow service configuration on class level
DaDeather added a commit to DaDeather/symfony that referenced this issue Jan 26, 2024
…llow service configuration on class level
@fabpot fabpot closed this as completed May 2, 2024
fabpot added a commit that referenced this issue May 2, 2024
…e to allow service definition at the class level (DaDeather, nicolas-grekas)

This PR was merged into the 7.1 branch.

Discussion
----------

[DependencyInjection] Add `#[AutowireInline]` attribute to allow service definition at the class level

| Q             | A
| ------------- | ---
| Branch       | 7.1
| Bug fix      | no
| New feature  | yes
| Deprecations | no
| Issues        | Fix #52819
| License       | MIT

For the idea behind this feature see the issue that contains examples #52819

### Example usage:
```php
class SomeSourceAwareLogger
{
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly string $someSource,
    ) {
    }
}

class SomeSourceAwareLoggerFactory
{
    public function __construct(
        private readonly LoggerInterface $logger,
    ) {
    }

    public function create(string $someSource): SomeSourceAwareLogger
    {
        return new SomeSourceAwareLogger($this->logger, $someSource);
    }

    public static function staticCreate(LoggerInterface $logger, string $someSource): SomeSourceAwareLogger
    {
        return new SomeSourceAwareLogger($logger, $someSource);
    }
}

// -----------

class SomeClass1
{
    public function __construct(
        #[AutowireInline(class: SomeSourceAwareLogger::class, args: [new Reference(LoggerInterface::class), 'bar'])]
        public SomeSourceAwareLogger $someSourceAwareLogger,
    ) {
    }
}

// AND/OR

class SomeClass2
{
    public function __construct(
        #[AutowireInline(
            class: SomeSourceAwareLogger::class,
            factory: [SomeSourceAwareLoggerFactory::class, 'staticCreate'],
            args: [new Reference(LoggerInterface::class), 'someParam'],
        )]
        public SomeSourceAwareLogger $someSourceAwareLogger,
    ) {
    }
}

// AND/OR

class SomeClass3
{
    public function __construct(
        #[AutowireInline(
            class: SomeSourceAwareLogger::class,
            factory: [new Reference(SomeSourceAwareLoggerFactory::class), 'create'],
            args: ['someParam'],
        )]
        public SomeSourceAwareLogger $someSourceAwareLogger,
    ) {
    }
}
```

Commits
-------

b9a838e Finish implementing AutowireInline attribute
a596142 [DependencyInjection] Add `#[AutowireInline]` attribute to allow service definition at the class level
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants