This chapter is part of the Drupal Module Developer Guide.
This chapter introduces the concepts of services and dependency injection. You’ll learn about the role of services in writing maintainable and reusable code, how to use any of the many useful services provided by Drupal core, and how to encapsulate your own custom business logic into a service. This chapter builds on the code started in the previous chapter and refactors it according to Drupal best practices.
As a development framework, Drupal core includes services for doing common things like accessing the database, sending email, or making HTTP requests. You can make use of these services to perform certain tasks, instead of recreating them in your own code. This means less custom code that you need to write and maintain. Generally speaking, almost everything that Drupal does is actually done by one of these objects. In Drupal, these objects are called services and in order to make working with them easier, they are primarily accessed through the service container.
In this tutorial, we'll:
- Explain the role of services in Drupal.
- Introduce the service container.
By the end of this tutorial, you'll understand the basics concepts of services and the service container in Drupal module development.
Dependency injection is an object-oriented programming design pattern widely used in Drupal. Instead of a class creating an object directly, dependency injection provides services or objects to a class externally, and is an example of the Inversion of Control principle.
In this tutorial, we'll:
- Explain dependency injection in the context of Drupal.
- Take a look at examples of constructor and setter injection in Drupal code.
By the end of this tutorial, you'll recognize dependency injection patterns and understand how it's used in Drupal module development.
To access services in Drupal through the service container, you'll need to know the unique machine name of the service. We'll use the example of making HTTP requests to a weather forecast API in the anytown module to demonstrate several methods you can use to identify an existing service's ID.
In this tutorial, we'll:
- Discover existing services and their machine names.
- Take a look at an example service definition.
By the end of this tutorial, you should be able to locate and use existing services in your Drupal module.
Controllers in Drupal frequently need to use services to figure out what information to display on the page. This might include querying for a list of entities, getting information about the current user, or accessing saved configuration. It's a best practice to always use dependency injection to supply services to a controller. In the anytown module we can improve the WeatherPage
controller by making it access a weather forecast API to get up-to-date data.
In this tutorial, we'll:
- Set up a mock weather forecast API.
- Refactor our
WeatherPage
controller to inject thehttp_client
andlogger.factory
services. - Update the
build()
method of our controller to use the provided services to get and display a weather forecast.
By the end of this tutorial you should be able to use dependency injection to give a controller in a Drupal module the services it requires, and then make use of those services in building the page content.
Custom services in Drupal modules encapsulate specific business logic or functionality. In our example, we'll demonstrate moving code required to access a weather forecast API from a controller into a service. This will help make our controller thin and our module code more reusable, testable, and maintainable.
In this tutorial, we'll:
- Explore the advantages of custom services for managing business logic.
- Define the components of a custom service.
By the end of this tutorial, you'll understand why creating custom services is a beneficial practice in Drupal module development.
The logic for retrieving and processing a weather forecast is hard-coded into the WeatherPage
controller. To make our code more reusable, maintainable, and organized, we can refactor this code into a custom weather forecast API service.
In this tutorial, we'll:
- Define a PHP interface for a weather forecast API service and write an implementation of that service.
- Create a service definition file to inform Drupal about our new service and its dependencies.
- Refactor the
WeatherPage
controller to use the new service, which will clean up duplicate code.
By the end of this tutorial, you'll be able to define and use a custom service in a Drupal module.