Drupal 8, essendo basato su Symfony, fa un forte utilizzo dei servizi.
In Symfony un servizio è definito come un oggetto PHP che svolge un determinato compito a livello globale, come per esempio inviare email oppure connettersi al database.
Questi servizi possono poi essere utilizzati in qualsiasi punto dell’applicazione.


Come detto, per creare un servizio basta semplicemente creare un oggetto, sembra quindi non esserci nulla di speciale, ma il vero vantaggio di pensare orientati ai servizi è quello di poter separare le funzionalità principali e comuni per poi utilizzarle ovunque nella nostra applicazione.
Questo ci permette di non doverci preoccupare delle singole operazioni, perché ci basta richiamare il servizio che le effettua.
 

Inoltre, avere tanti piccoli pezzi indipendenti ci permette di estendere la nostra applicazione aggiungendo semplicemente nuovi servizi, ma ci consente anche di sostituire la classe che effettua un servizio con la sola modifica di una configurazione; ancora, ci permette di poter riutilizzare un servizio tra un’applicazione e l’altra, perché svolgendo un singolo task indipendente basta portare la classe PHP da un progetto all’altro.

Un altro vantaggio è dato dal livello di astrazione creato dai servizi, che facilita il lavoro dello sviluppatore, l’esempio più immediato è il servizio per connettersi al database: all’interno dell’applicazione verrà sempre chiamato il servizio, ma sarà lui a dover gestire se il database è Mysql, SQLlite o altro ancora.
 

Drupal 8 utilizza fortemente i servizi già in core, per avere una lista completa il miglior metodo è guardare CoreServiceProvider.php o core.services.yml.

 

Per facilitare ulteriormente lo sviluppatore, oltre ai servizi vengono creati dei service container, delle classi PHP che hanno lo scopo di orchestrare i servizi.
In Drupal il service container è gestito dalla classe Drupal e fornisce già una serie di metodi statici utili a recuperare direttamente buona parte dei servizi in core, come il database, l’utente corrente o la lingua corrente:

 

$connection = \Drupal::database();
$user = \Drupal::currentUser();
$language =  \Drupal::languageManager()->getCurrentLanguage()->getId();

 

Per gli altri possiamo sempre recuperare il servizio attraverso il metodo statico service. Nell’esempio seguente vediamo come si è “trasformata” la funzione drupal_render presente in Drupal 7:

 

 

$html = \Drupal::service('renderer')->render($elements, FALSE);

 

Nonostante la classe Drupal ci permetta di accedere facilmente ai servizi, il metodo migliore per utilizzarli è attraverso la dependency injection, che si effettua richiamando il servizio all’interno delle nostre classi nel costruttore o attraverso dei setter (metodi per valorizzare una variabile).

Per esempio per utilizzare l’entity manager all’interno della nostra classe dobbiamo:

  1. Definire la proprietà nella classe
  2. Nel costruttore associare il servizio alla nostra proprietà
  3. Nella funzione create richiamare il servizio

 

protected $entityManager;

  /**
   * Constructs a ContentEntityForm object.
   *
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   *   The entity manager.
   */
  public function __construct(EntityManagerInterface $entity_manager) {
    $this->entityManager = $entity_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.manager')
    );
  }

 

Così facendo all’interno della nostra classe potremo richiamare il servizio attraverso la proprietà:

 

 

$this->entityManager->getTranslationFromContext(…)

 

L’ultimo step per poter utilizzare a pieno i servizi è quello di definirne di nuovi; per farlo abbiamo visto che basta creare una classe PHP, il tassello mancante è in che modo dire a Drupal di collegare il nuovo servizio.
Per farlo basta creare nel nostro modulo un file YAML my_module.services.yml dove verrà definito il servizio, come per esempio in block.services.yml

 

services:
  theme.negotiator.block.admin_demo:
    class: Drupal\block\Theme\AdminDemoNegotiator
    tags:
      - { name: theme_negotiator, priority: 1000 }
  block.page_display_variant_subscriber:
    class: Drupal\block\EventSubscriber\BlockPageDisplayVariantSubscriber
    tags:
      - { name: event_subscriber }
  block.repository:
    class: Drupal\block\BlockRepository
    arguments: ['@entity.manager', '@theme.manager', '@context.handler']

 

Giuseppe Del Gaudio