Drupal 8: Creating your own services

In a recent project there was the need to create a new class that could be used as a service in Drupal 8 as it would contain quite a few reusable functions.
Create the following directory and file structure in your custom module.
Let’s take one file at a time.
src/MyModuleCharts.php
<?php
namespace Drupal\mymodule;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Datetime\DateFormatter;
/**
* Class MyModuleCharts.
*
* @package Drupal\mymodule
*/
class MyModuleCharts {
/**
* Logger service.
*
* @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
*/
protected $logger;
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* Date Formatter.
*
* @var \Drupal\Core\Datetime\DateFormatter
*/
protected $dateFormatter;
/**
* The current user account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* MyModuleCharts constructor.
*
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger
* The logger service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* The date formatter service.
*/
public function __construct(
LoggerChannelFactoryInterface $logger,
EntityTypeManagerInterface $entity_type_manager,
DateFormatter $date_formatter,
AccountInterface $account) {
$this->logger = $logger->get('mymodule_charts');
$this->entityTypeManager = $entity_type_manager;
$this->dateFormatter = $date_formatter;
$this->currentUser = $account;
}
/**
* Update some chart value.
*
* @param object $entity
* The entity object.
* @param int $value
* The value to set.
*
* @throws \Exception
*/
public function setSomeChartValue($entity, $value) {
// Do something.
}
/**
* Calculate some value to set.
*
* @param int $value
* The value set.
* @return int
* The value to set after calculation.
*/
public function calculateSomeChartValue($value) {
// Do something.
}
}
This is the service class that we will have our reusable functions, these functions can then be used anywhere that we load our service. I have included some dependencies via injection just for example purposes.
mymodule.services.yml
services:
mymodule.charts:
class: 'Drupal\mymodule\MyModuleCharts'
arguments: ['@logger.factory', '@entity_type.manager', '@date.formatter', '@current_user']
The services YAML file is used to let Drupal know that this class is a service and can be loaded by using \Drupal::service('mymodule.charts');
if inside a .module
file or injected as a dependency if working in a Controller or other Class.
Using the service class in a .module file
To load our new service in a .module we can use the following code:
/** @var \Drupal\mymodule\MyModuleCharts $mymodule_charts_service */
$mymodule_charts_service = \Drupal::service('mymodule.charts');
In the example I have used the @var
inline variable type declaration /** @var \Drupal\mymodule\MyModuleCharts $mymodule_charts_service */
this is useful if you are using PHPStorm or any other PHP IDE, as it gives you autocompletion of method names on your service class.
Using the service class in a Controller via Dependency Injection
<?php
namespace Drupal\mymodule\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\mymodule\MyModuleCharts;
/**
* Class MyModuleController
*
* @package Drupal\mymodule\Controller
*/
class MyModuleController extends ControllerBase implements ContainerInjectionInterface {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Date Formatter.
*
* @var \Drupal\Core\Datetime\DateFormatter
*/
protected $dateFormatter;
/**
* MyModule Charts service.
*
* @var \Drupal\mymodule\MyModuleCharts
*/
protected $myModuleChartsService;
/**
* MyModuleConstructor constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\Core\Datetime\DateFormatter $date_formatter
* The date formatter service.
*/
public function __construct(
EntityTypeManagerInterface $entity_type_manager,
DateFormatter $date_formatter,
MyModuleCharts $mymodule_charts_service) {
$this->entityTypeManager = $entity_type_manager;
$this->dateFormatter = $date_formatter;
$this->myModuleChartsService = $mymodule_charts_service;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager'),
$container->get('date.formatter'),
$container->get('mymodule.charts')
);
}
/**
* Some Controller type function goes here.
*
* @return array
*/
public function someControllerTypeFunction() {
// Do something amazing here!
// Use the myModuleChartsService here.
$this->myModuleChartsService->calculateSomeChartValue();
return [];
}
}
Please leave a comment with any feedback or if you feel I have explained something incorrectly.