Drupal 8 Services
Phil Norton
Drupal::service('thing');
Wrap objects.
Define a common interface.
Dependency Injection.
Powerful.
Certified awesome.
uuid
date
queue
cache
menu
translation
entity
config
cron
renderer
path
route
file_system
plugin
$pathManager = Drupal::service('path.alias_manager');
$path = 'somepath';
$normal_path = $pathManager->getPathByAlias($path);
$normal_path = Drupal::service('path.alias_manager')
->getPathByAlias('somepath');
Services are defined in yml files
<module>.services.yml
queue.database:
class: DrupalCoreQueueQueueDatabaseFactory
arguments: ['@database']
path.alias_whitelist:
class: DrupalCorePathAliasWhitelist
tags:
- { name: needs_destruction }
arguments: [path_alias_whitelist, '@cache.bootstrap', '@lock', '@state', '@path.alias_storage']
path.alias_manager:
class: DrupalCorePathAliasManager
arguments: ['@path.alias_storage', '@path.alias_whitelist', '@language_manager', '@cache.data']
path.current:
class: DrupalCorePathCurrentPathStack
arguments: ['@request_stack']
Altering Services
Problem: Shield module prevents testing of API service on
staging website.
Solution: Poke a hole in the shield!
Module shield_override
shield_override.info.yml
src/ShieldOverrideServiceProvider.php
src/ShieldOverride.php
<?php
namespace Drupalshield_override;
use DrupalCoreDependencyInjectionContainerBuilder;
use DrupalCoreDependencyInjectionServiceProviderBase;
class ShieldOverrideServiceProvider extends ServiceProviderBase {
public function alter(ContainerBuilder $container) {
// Decorate the shield module to prevent it from triggering on certain
// routes.
$definition = $container->getDefinition('shield.middleware');
$definition->setClass('Drupalshield_overrideShieldOverride');
}
}
namespace Drupalshield_override;
use DrupalshieldShieldMiddleware;
use SymfonyComponentHttpFoundationRequest;
class ShieldOverride extends ShieldMiddleware {
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
// Get the current request URI.
$currentPath = $request->getRequestUri();
// Get the current method (e.g. GET or POST).
$currentMethod = $request->getMethod();
if (($currentMethod == 'POST' || $currentMethod == 'GET')
&& strstr($currentPath, '/the/soap/service/path) !== FALSE) {
// If we are attempting to access the soap controller via a post HTTP
// method then handle the request without invoking the Shield module.
return $this->httpKernel->handle($request, $type, $catch);
}
// Always handle the request using the default Shield behaviour.
return parent::handle($request, $type, $catch);
}
}
Create Your Own
<module>.services.yml
services:
<service name>:
class: Drupal<full namespace of service class>
arguments: ['@config.factory']
PCA Predict Module
services:
pcapredict:
class: Drupalpcapredict_integrationPcaPredictPcaPredict
arguments: ['@config.factory']
namespace Drupalpcapredict_integrationPcaPredict;
use DrupalCoreConfigConfigFactoryInterface;
use Drupalpcapredict_integrationPcaPredictPcaPredictInterface;
class PcaPredict implements PcaPredictInterface {
protected $pcaPredictKey;
public function __construct(ConfigFactoryInterface $config_factory) {
$this->pcaPredictKey = $config_factory->get('pcapredict_integration.settings')->get('pcapredict_apikey');
}
public function find(array $values, $type = 'json') {
// Load data from the API.
}
public function retrieve(array $values, $type = 'json') {
// Load data from the API.
}
}
Problem: Testing PCA Predict needs an API account and
costs money per transaction.
Solution: Create a service override that doesn’t use the API.
New module called PCA Predict integration stub
pcapredict_integration_stub.info.yml
src/PcaPredictIntegrationStubServiceProvider.php
src/PcaPredict/PcaPredictStub.php
namespace Drupalpcapredict_integration_stub;
use DrupalCoreDependencyInjectionContainerBuilder;
use DrupalCoreDependencyInjectionServiceProviderBase;
class PcaPredictIntegrationStubServiceProvider extends ServiceProviderBase {
public function alter(ContainerBuilder $container) {
// Override the PcaPredict class with a new class.
$definition = $container->getDefinition('pcapredict');
$definition->setClass('Drupalpcapredict_integration_stubPcaPredictPcaPredictStub');
}
}
namespace Drupalpcapredict_integration_stubPcaPredict;
use Drupalpcapredict_integrationPcaPredictPcaPredictInterface;
use DrupalCoreConfigConfigFactoryInterface;
class PcaPredictStub implements PcaPredictInterface {
protected $pcaPredictKey;
public function __construct(ConfigFactoryInterface $config_factory) {
$this->pcaPredictKey = $config_factory->get('pcapredict_integration.settings')->get('pcapredict_apikey');
}
public function find(array $values, $type = 'json') {
// Load data from a CSV file.
}
public function retrieve(array $values, $type = 'json') {
// Load data from a CSV file.
}
}
find() / retrieve()
API
Address finder
find() / retrieve() Address finder
Resources
Documentation
https://api.drupal.org/api/drupal/core%21core.api.php/group/container/8.3.x
List of all services
https://api.drupal.org/api/drupal/services

Drupal 8 Services