If that title sounds a bit too technical, don’t worry—we're going to break it down into something much simpler.
Let’s imagine you’ve got a Drupal e-commerce site and you want to give a little something extra to your high-spending customers. Let’s say, if someone spends over $500, they get free shipping. The problem? Your current shipping service calculates rates based on weight and location, without considering order value.
So, how do you introduce this free shipping rule without tearing apart your existing system? This is where overriding services in Drupal comes in handy.
With a simple tweak using a service provider, you can override the default shipping calculator service to include a custom rule like this.
Drupal’s service container makes this possible, allowing you to define and override services easily. A service provider in Drupal is essentially a PHP class that extends ServiceProviderBase, giving you the power to alter or replace existing services without touching core code.
Let's walk through how you can do that step-by-step.
Understanding Services in Drupal
What is a Service?
In Drupal, a service is a PHP object that encapsulates a particular piece of functionality. Services can handle tasks like logging, sending emails, routing, etc. These services are defined in a *.services.yml file and managed by Symfony's Dependency Injection component, part of the underlying framework.
The Service Container
Drupal uses a service container to manage and retrieve services. The service container is a registry that holds all services available within Drupal and is responsible for creating and injecting these services wherever they are needed in the application.
Why Override a Service
Customization
You may need to override a service in Drupal to alter its behavior. For example, you might want to customize how the logging service handles log messages.
Extend Functionality
Overriding a service allows you to extend its functionality. For instance, you could add additional processing steps before an email is sent.
Maintainability
By overriding a service in your custom module, you can avoid modifying core or contributed modules directly, making your customizations easier to maintain and upgrade-safe.
Overriding a custom service using a service provider in Drupal
Step 1: Identify the service to override
Let’s assume you are working with a service that logs information. The service is defined in the module custom_module in the file custom_module.services.yml :
# modules/custom/custom_module/custom_module.services.yml
services:
custom_module.custom_logger:
class: Drupal\custom_module\CustomLoggerService
arguments: ['@logger.factory']
Here, custom_module.custom_logger is a service that uses the class CustomLoggerService and injects a logger service (@logger.factory) into it.
Below is the sample code of CustomLoggerService.php:
<?php
namespace Drupal\custom_module;
use Drupal\Core\Logger\LoggerChannelFactory;
class CustomLoggerService {
/**
* The logger channel factory.
*
* @var \Drupal\Core\Logger\LoggerChannelFactory
*/
protected $loggerFactory;
/**
* Constructs a CustomLoggerService object.
*
* @param \Drupal\Core\Logger\LoggerChannelFactory $loggerFactory
* The logger channel factory service.
*/
public function __construct(LoggerChannelFactory $loggerFactory) {
$this->loggerFactory = $loggerFactory;
}
/**
* Logs a message.
*/
public function info() {
$logger = $this->loggerFactory->get('service_override');
// Log a message to the 'service_override' channel.
$logger->info('Logger without service overriding.');
// Add a status message.
return "Tech-x without overriding service";
}
}
Step 2: Create a new module for the override
You can create a new module or use the existing module, that will override this service. Let’s call it custom_override. This module will contain the service provider that overrides the custom_module.custom_logger service.
Create the module directory:
Create the following directory structure for your custom module:
/modules/custom/custom_override/
Create the module Info file:
Create a custom_override.info.yml file for the module:
# modules/custom/custom_override/custom_override.info.yml
name: 'Custom Override'
type: module
description: 'Overrides services from the custom module.'
core_version_requirement: ^10
dependencies:
- custom_module
Step 3: Create a service provider
A service provider in Drupal allows you to modify, override, or extend the services provided by other modules. Create a service provider class in your custom module.
Create the service provider class
Create the src/CustomOverrideServiceProvider.php file under the custom_override module.
# modules/custom/custom_override/src/CustomOverrideServiceProvider.php
namespace Drupal\custom_override;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
/**
* Alters the custom_module services.
*/
class CustomOverrideServiceProvider extends ServiceProviderBase {
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container) {
// Check if the service exists before overriding.
if ($container->hasDefinition('custom_module.custom_logger')) {
// Override the service definition.
$definition = $container->getDefinition('custom_module.custom_logger');
// Set the class to a new class in this module.
$definition->setClass('Drupal\custom_override\OverrideLoggerService');
}
}
}
In this code, we are using the alter() method to check if the custom_module.custom_logger service exists. If it does, we override it by setting a new class (OverrideLoggerService).
Register the service provider
Drupal 10 automatically discovers service providers if they are placed correctly, so you don’t need to declare the service provider explicitly in your .services.yml file. Drupal will automatically register the CustomOverrideServiceProvider.
Step 4: Create the overridden service class
Now, create the new service class that will override the original service. In this example, we’ll extend the functionality of the CustomLoggerService class.
# modules/custom/custom_override/src/OverrideLoggerService.php
namespace Drupal\custom_override;
use Drupal\custom_module\CustomLoggerService;
/**
* Overrides the CustomLoggerService class.
*/
class OverrideLoggerService extends CustomLoggerService {
/**
* Logs a custom message with additional details.
*/
public function info() {
// Add custom logic here, e.g., append more information to the log.
$message = 'Logger with service overriding (Overridden by custom_override).';
// Log the message.
$this->loggerFactory->get('service_override')->info($message);
// Add a status message.
return "Tech-x with overriding service";
}
}
In this class, we’re extending the original CustomLoggerService and overriding the info() method. We append a custom message to the log entry before calling the logger service.
Step 5: Clear the Cache and Test the Override
After setting up the service provider and the new class, you need to clear the Drupal cache to register the new service definition:
drush cr
Once the cache is cleared, any place in the code where custom_module.custom_logger is used and will now utilize the overridden OverrideLoggerService class.
Steps summarized
Identify the service to override in the original module.
Create a new module (optional) or add a service provider in the same module.
Implement the service provider using the ServiceProviderBase class and override the service.
Create a new service class that replaces the original one.
Clear Drupal’s cache to make sure the new service provider is recognized.
Test the overridden service to confirm it’s working as expected.
Final thoughts
By following these steps, you can easily override any service in Drupal 10 using a service provider and customize the behavior of your services to meet your specific needs. Drupal’s service architecture provides a clean, modular way to extend your site without compromising its core stability. With a little know-how, you can make Drupal work exactly how you want, while keeping your code maintainable and future-proof.
Need help with customizing your Drupal site? Explore our range of Drupal development services and let our experts help you build it your way.