Dependency Injection (also DI) is a framework mechanism for supplying dependencies to the constructor or other methods of created objects.
When the framework creates objects such as controllers, middlewares, commands, and others, dependency injection is already set up when the target method (including the constructor) is called.
According to the DI mechanism, if you specify the necessary classes or interfaces in the method's dependencies (arguments), the framework will attempt to find such matches in the container, retrieve them from the container, or create the object itself and substitute it in the required argument.
If such a service is not found in the container, an attempt will be made to create an object from a suitable class in the project, and if the latter has dependencies in its constructor, the framework will try to fill them in a similar way.
If there are no substitution values for arguments with default values, the default will be used.
Otherwise, the framework will return an error indicating that the DI for the specified dependencies could not be successfully used.
When a controller or middleware object is created on the framework side, the constructor's dependencies are resolved first, then those of the called method.
Also, when a request is processed by the framework, only one method in the matched controller will be called. In such a case, it doesn't matter where the dependency comes from, whether from the constructor or method, although in some cases, the constructor is more convenient.
The following example shows two controller methods with different assignments of $logger from the container via DI.
Dependencies for middleware are set in a similar manner.
In the framework commands and events (Events), this is implemented in a similar way, but only through the constructor:
Dependency injection is convenient because during testing, we can create the necessary values for class dependencies. However, when creating an object manually, initializing all its dependencies ourselves would be inconvenient. To automate this process, the framework provides the Hleb\Static\DI class.
This section demonstrates how to create an object of a class whose constructor has a dependency, and how to call the desired method of the object where a value also needs to be automatically inserted. The example also shows a dependency that is not from the container (the Insert class), whose object is created and injected into the method.
A frequently used variant of DI with Request and Response (in this case obtained from the container):
Due to various approaches in interface naming conventions, obtaining standard services from the container may involve interfaces ending with Interface or not. For example, Hleb\Reference\RequestInterface is equivalent to Hleb\Reference\Interface\Request.
As mentioned earlier, if the framework cannot find a dependency in the container while resolving dependencies, it will attempt to create an object of the specified class on its own and resolve that class's dependencies if they are specified in the class constructor.
There are ways to indicate which path should be followed in such cases. The configuration parameter system.autowiring.mode sets the management mode for such dependencies. There is a mode in which you can completely disable autowiring for dependencies not found in the container and a mode similar to this, but allowing the use of a class object when the AllowAutowire attribute is present, as well as the NoAutowire attribute that disallows autowiring for the current class if the permitting mode with support for this attribute is enabled.
Using the special DI attribute, you can specify in a specific location (class method) which particular dependency with the specified interface should be used. If such a dependency from the attribute is found in the container, it will be used from the container. If not, the same rules for autowiring dependencies not found in the container apply as if it were specified directly in the method. Examples:
It shows options for how to specify a specific class from the required interface in the parameter, as well as creating the necessary class in the attribute.
← Retrieving Service Request →