Skip to content
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

Dependency Injection does not work when constructor parameters are given #5118

Open
cweiske opened this issue Dec 2, 2024 · 5 comments
Open

Comments

@cweiske
Copy link
Contributor

cweiske commented Dec 2, 2024

Current behavior

The "Dependency Injection" page does not mention the fact that DI is not applied when constructor parameters are given.

https://docs.typo3.org/m/typo3/reference-coreapi/11.5/en-us/ApiOverview/DependencyInjection/Index.html#method-injection

Method injection is something that could still work when GeneralUtility::makeInstance() is called with constructor parameters, but DI is only applied when no parameters are given.

Expected behavior/output

The DI documentation should describe that classes with constructor parameters cannot be used for DI at all.

Links

public static function makeInstance($className, ...$constructorArguments)
{
    [...]
    // Read service and prototypes from the DI container, this is required to
    // support classes that require dependency injection.
    // We operate on the original class name on purpose, as class overrides
    // are resolved inside the container
    if (self::$container !== null && $constructorArguments === [] && self::$container->has($className)) {
        return self::$container->get($className);
    }
    [...]
}

TYPO3 versions

11, 12, 13

@froemken
Copy link
Contributor

froemken commented Dec 5, 2024

In docs for TYPO3 12 I found following sentence:

Every class that is instantiated using GeneralUtility::makeInstance() and requires dependency injection must be marked as public. The same goes for instantiation via GeneralUtility::makeInstance() using constructor arguments.

I also don't understand why I should mark an object which is called with constructor arguments should be marked public: true as it was not instanciated by DI. IMO such classes should be excluded from DI instead.

@cweiske
Copy link
Contributor Author

cweiske commented Dec 6, 2024

The problem is known and described in one changelog entry:
Deprecation: #94317 - ext:form Finisher implementations

In contrast to Extbase object management, symfony DI does not support prototype classes with a mixture of manual constructor arguments, plus dependency injection via other constructor arguments or inject methods.

@garvinhicking
Copy link
Contributor

You can actually use constructor arguments with DI. Symfony services.yaml allows you to define constructor arguments (using "bind" or "arguments").

@cweiske
Copy link
Contributor Author

cweiske commented Dec 9, 2024

But no dynamic ones.
When I do GeneralUtility::makeInstance($myClass, $param1, $param2), dependencies do not get injected (not even the inject* methods get called!). This is what I am talking about.

@garvinhicking
Copy link
Contributor

Sure. But we need to have an adjustment that takes this into account.

I would suggest to add a sentence to https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DependencyInjection/Index.html#arguments along these lines:

"If you use GU::makeInstance() on any class that has custom constructor arguments (apart from DI) you must specify all parameters on your own, because no automatism can be applied.

(Insert example of GU::mI() that would fail and show passing all arguments, or recommending to not use constructor based special parameters but instead setters()/variable injection so that constructors are purely used for DI, or to advise not using GU:mI at all and using Services.yaml wiring like above. Or purely using constructor for arguments and make the whole class uses method injection.)

Note that if you use classes with custom constructor arguments with regular DI configration, you can pass/bind arguments to the constructor call via the Services.yaml registration, as seen in the example above.
"

(Sidenote: thumbs-downing a valid note from someone who's trying to help isn't really motivating.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants