18 \ December 2018 \ http://www.phparch.com
The Flexibility of Drupal 8
Replacing an existing service requires an experienced back-
end developer with knowledge of writing Object Oriented
PHP. Implementing a custom service to replace an existing
one requires a custom Drupal module. The custom Drupal
module includes the new service. Be careful! If we don’t pay
adequate attention, replacing a service may prevent parts of a
Drupal instance from working. Consider all of the function-
ality that a service may impact to avoid this possibility.
Discovering Services
No direct mechanism for discovering which services exist,
but there are developer tools that can help. All services are
defined in *.services.yml files, including the ones defined by
Drupal core. Developers can review these files to determine
which service to replace.
Service definition snippet from the core.services.yml file
in Drupal 8 core.
services:
Simple cache contexts, directly derived from
the request context.
cache_context.ip:
class: Drupal\Core\Cache\Context\IpCacheContext
arguments: ['@request_stack']
tags:
- { name: cache.context }
Developers can also use the command line tool Drupal
Console to list available services. Drupal Console is avail-
able for download at https://drupalconsole.com. As shown
in Figure 14, running the command drupal debug:container
lists of all the available services.
Changing a Menu Item Using a Service
Reviewing the available core services in core/core.services.
yml, reveals the menu.link_tree service. This PHP class is
responsible for building the array of items for all menus in
Drupal. Replacing this service with a custom version allows
altering the main menu when it is initially built. The Sweet
module created in the previous example defines this custom
service.
Replacing an existing service requires two PHP classes in
two files. The first file contains a class that tells Drupal which
PHP class to use rather than the default. The second file
contains the class which replaces the service.
The first file, modules/custom/sweet/src/SweetServicePro-
vider.php, defines the class SweetServiceProvider. This class
extends the core ServiceProviderBase class and implements
the alter() method. This method retrieves the definition for
the menu.link_tree service and then replaces the class used
with a custom PHP class.
Replacing the class used by the menu.link_tree class as
defined in src/SweetServiceProvider.php.
class SweetServiceProvider extends ServiceProviderBase {
public function alter(ContainerBuilder $container) {
// Retrieve definition for the menu.link_tree service.
$definition = $container->getDefinition('menu.link_tree');
// Replace class used for service with custom class.
$definition->setClass('Drupal\sweet\SweetMenuLinkTree');
}
}
The second file, modules/custom/sweet/src/SweetMenuLink-
Tree.php, contains the new class to use for the service. The
class SweetMenuLinkTree extends the base MenuLinkTree class.
By extending the base, Drupal uses all core functionality
except for the specific methods that the custom class over-
rides.
The method responsible for building the menu tree is
build(). As shown in Listing 7, custom logic overrides this
method. The new method first calls the parent method to
generate the menu tree. The method then checks if we are
generating the main menu; if so, it replaces the “Contact”
item. This item now points to a randomly selected recipe and
titles it “Mystery Meal”.
To build the main menu, Drupal now uses our custom
service class. The new service replaces the “Contact” menu
item with a link to a random recipe, labeling “Mystery Meal”,
as shown in Figure 15.
Figure 14
Figure 15