Drupal 8+ is build upon Services and many place of the system available through the Dependency injection. So its important to understand the concept of services and DI.
Services : Service is any object managed by the services container. or we can say that services is a simple PHP class with some methods. we can access these services and methods in anywhere in the application with the help of service container.
The service can be used the in following way. We use the \Drupal::service() method to get an instantiated AliasManager object and then use a function in that object to translate the path to the alias.
$aliasManager = \Drupal::service(‘path_alias.manager’);
$path = ‘/node/123’;
$alias = $aliasManager->getAliasByPath($path);
Accessing Services: Services are all defined in YML files within Drupal. Every module that wants to define a service needs to create a file with the name of [module name].services.yml . In order to find all the available services in Drupal you can follow the services list .
So best practice for accessing the services is dependency injection instead of direct calling the global Drupal service container.
Dependency Injection : Dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. It means we can directly inject the services to the class __construct method, and it will load the dependency runtime when instantiate the class.
Why use DI in Drupal :
- Decoupled functionality
- Eases unit testing
- Reusable & flexible code
- Cleaner code
- Retrieving dependencies from the container is better for performance.
How to Inject Dependency :
Before implementing the DI let’s have a look the code without DI. So i am just displaying the current user name in the render function. In the below code line no 13 and 14 i am using the Drupal function to get the username,
Example code without DI.
its also working fine but Drupal recommend to use Dependency Injection everywhere. So let’s start to inject the Dependency Injection on same code base.
Example code With DI :
Example 1: DI with in Controller
I have created the simple render function within the controller , Here I am using the Dependency Injection to get the current user details based on the current_user services.
There is 2 main function to execute the DI in Drupal __construct() & create().
__Construct Method : With in the construct method we define all the services which we need as a DI.
Create Method : Create() method is a factory method based on the factory design Pattern.
create() method help us to create the instance of the all the services which we pass in the create() method. Return new static() means “Return a new instance of the current class, using the passed arguments in the class’s constructor”
So technically all the arguments and order of the arguments would be the same in both the create() and construct() function.
Same as above we can define the DI in FormBase, configFormBase etc
Example 2 : Dependency Injection in services class
For services DI we are taking the example of core node.service.yml
That is saying that for the
Drupal\node\NodeGrantDatabaseStorageclass will be used, and three arguments will be passed to it when creating an instance of it.
@ symbol means that these are instances of other services. An instance of a
database service, a
module_handler service, and a
language_manager service will be provided to this node.grant_storage service. These services are just objects of designated types.
Here’s the relevant portion of the NodeGrantDatabaseStorge class. I’ve added line breaks to this and other code samples for readability.
The three arguments used in the constructor match the three arguments defined in the services file. The passed Object are then stored as properties of the class. In other word, the three objects (dependencies) were injected into the client class (NodeGrantDatabaseStorage) by the services system.Example 3: Dependency Injection Inside Block (Plugin)
Example 3: Dependency Injection Inside Block (Plugin)
We can inject our custom/core service inside our custom block plugin for that we have to use.
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;Suppose you have a custom block with the name 'drupalise' then you inject your custom service 'drupalise' inside your custom block code as follows:
Here drupalise is my custom service which has the function Drupalise().
That’s All in Drupal Dependency Injection. Happy Drupaling.