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

Skip to content

[DependencyInjection] add factory argument in the #[Autoconfigure] attribute and also enabled the use of factory within instanceof conditionals #60589

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

Open
wants to merge 1 commit into
base: 7.4
Choose a base branch
from

Conversation

santysisi
Copy link
Contributor

@santysisi santysisi commented May 30, 2025

Q A
Branch? 7.4
Bug fix? no
New feature? yes
Deprecations? no
Issues no
License MIT

This PR adds support for a new factory argument in the #[Autoconfigure] attribute. It also enables the use of factory in instanceof conditionals across all configuration formats.

The factory argument allows developers to specify how the service should be instantiated, using the same factory syntax already supported in service definitions.

✅ Usage Example

<?php

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;

#[Autoconfigure(factory: '@=service("app.factory.expression").make()')]
class WithExpressionFactory
{
    public function __construct(public readonly string $foo) {}
}

#[Autoconfigure(
    bind: ['$foo' => 'bar'],
    factory: ['@App\\Factory\\InstanceFactory', 'build']
)]
class WithInstanceMethodFactory
{
    public function __construct(public readonly string $foo) {}
}

#[Autoconfigure(
    bind: ['$foo' => 'baz'],
    factory: '@App\\Factory\\InvokableFactory'
)]
class WithInvokableFactory
{
    public function __construct(public readonly string $foo) {}
}

#[Autoconfigure(
    bind: ['$foo' => 'qux'],
    factory: [\App\Factory\StaticFactory::class, 'create']
)]
class WithStaticFactory
{
    public function __construct(public readonly string $foo) {}
}

#[Autoconfigure(
    bind: ['$foo' => 'auto'],
    factory: [null, 'fromValue']
)]
class WithSelfStaticFactory
{
    public function __construct(public readonly string $foo) {}

    public static function fromValue(string $foo): static
    {
        return new self($foo);
    }
}

@carsonbot carsonbot added this to the 7.4 milestone May 30, 2025
@santysisi santysisi force-pushed the feature/as-factory-attribute branch 2 times, most recently from e09532c to 52cdb9a Compare May 30, 2025 03:25
@zolex
Copy link

zolex commented May 30, 2025

I like the feature and I know the As prefix for these attributes is common in symfony, but I wonder a bit about the semantics. Usually if I see a AsSomething attribute on a class, it means that the class with the attribute now is a Something. When null is passed as the class to the factory argument, the semantics are fine. But if you provide another classname, a service or even expression language, the As prefix seems semantically incorrect to me, because now it is not the class with the attribute that becomes the factory, but something else. So in the first place I would suggest to rename the Attribute to just Factory.

But thinking about it a bit more: I believe it would be a better option to reuse the existing Autoconfigure attribute, which has a constrcutor argument, that can be used for factories in the same class. At the moment it only allows a string, referencing a static method inside the same class. You could simply apply your logic on the existing attribute argument if it is an array.

@santysisi
Copy link
Contributor Author

Hi @zolex, thanks for your comment ❤️ I really appreciate it 😄
You're absolutely right, the semantics of the As prefix can be misleading, especially when an external factory is used. Renaming the attribute to just Factory makes a lot more sense.
I also really like your suggestion about reusing the existing Autoconfigure attribute. I’ll work on updating it to support arrays and apply the logic there as well.
I’ll make these changes as soon as possible. Thanks again for the valuable feedback! 🙏

@santysisi
Copy link
Contributor Author

I was thinking a bit about this, and I have a question 🤔
If we change the constructor argument to accept string|array|null, I believe we would end up with the same behavior as the factory.
So, my question is: maybe we can leave the constructor argument as it is today, and instead, add the factory argument to the AutoConfigure?

I’m asking this from a place of curiosity and ignorance, totally open to discussion if I’m missing something 🙂
Thanks! ❤️

@zolex
Copy link

zolex commented Jun 7, 2025

I was thinking a bit about this, and I have a question 🤔 If we change the constructor argument to accept string|array|null, I believe we would end up with the same behavior as the factory. So, my question is: maybe we can leave the constructor argument as it is today, and instead, add the factory argument to the AutoConfigure?

I would definitely prefer the argument to be called factory. If you introduce a factory argument, maybe also support a string for a method in the same class like constructor does and at the same time deprecate the constructor argument to prepare the people to migrate to the factory argument. It was a bad naming anyway.

@santysisi
Copy link
Contributor Author

I like that idea 😄 If others agree, I can go ahead and make that change:

  • Add a new argument called factory
  • Deprecate the constructor argument to help people migrate smoothly

@santysisi santysisi force-pushed the feature/as-factory-attribute branch 2 times, most recently from dd83b21 to 5b8b26d Compare June 18, 2025 23:03
@santysisi
Copy link
Contributor Author

Hi 👋 I hope you're all doing well ❤️

I've updated the PR description and made the necessary code changes. Please let me know if there's anything else you'd like me to adjust 😊

P.S. I haven’t deprecated the constructor argument yet but if you all agree that it should be deprecated, I’m happy to make that change as well.

P.P.S. The test failure doesn’t seem related to this PR, it looks like a flaky test.

Thanks! 😄

@norkunas
Copy link
Contributor

norkunas commented Jun 19, 2025

PR/commit title does not reflect your code here :)

@@ -100,6 +100,7 @@ class YamlFileLoader extends FileLoader
'autowire' => 'autowire',
'bind' => 'bind',
'constructor' => 'constructor',
'factory' => 'factory',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change the YamlFileLoader when the PR description talks only about attributes ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code internally uses the YamlFileLoader to read values found in attributes

this makes me wonder about the yaml + xml + php config formats: they should also support this factory entry

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we should indeed support it in all formats, and make the changelog entry (and the PR title and description) mention that explicitly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and we should also have tests preventing regressions for those other formats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @stof @nicolas-grekas 👋 I hope you're both doing well! 😊
I've made the requested changes, please let me know if there's anything else you'd like me to adjust. 😊

Thanks! ❤️

@santysisi santysisi force-pushed the feature/as-factory-attribute branch from 5b8b26d to 39fae23 Compare June 20, 2025 17:25
@santysisi santysisi force-pushed the feature/as-factory-attribute branch from 39fae23 to 138b1dd Compare June 20, 2025 17:28
@santysisi santysisi changed the title [DependencyInjection] add #[AsFactory] attribute [DependencyInjection] add factory argument in the #[Autoconfigure] attribute and also allow factory in instanceof Jun 20, 2025
@santysisi santysisi changed the title [DependencyInjection] add factory argument in the #[Autoconfigure] attribute and also allow factory in instanceof [DependencyInjection] add factory argument in the #[Autoconfigure] attribute and also enabled the use of factory within instanceof conditionals Jun 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants