
Drupal 8: Creando nuestro primer servicio
Autor: fjavimartin
Fecha de Creación: 22/01/2018
Categorías:
Los servicios en Drupal son una manera de crear una funcionalidad y ponerla a disposición de todos los módulos mediante el contenedor de servicios. Uno de los servicios más usados y que nos suministra el core de Drupal es ‘current_user’ que nos dará acceso al usuario actual.
Nuestro objetivo en este artículo será la creación de un servicio personalizado mediante el cuál podremos ejecutar una función que nos devuelva un “Hola Mundo”.
1. Fichero info.yml
Como otras veces, nuestro primer paso será la creación del fichero info.yml de nuestro módulo de ejemplo:
name: E-Quipos.es - Services
description: Test services.
type: module
package: E-Quipos
version: 8.x-1.0
core: 8.x
2. Fichero routing.yml
Para probar la funcionalidad de nuestro módulo crearemos un formulario al que inyectaremos nuestro servicio y en este fichero declararemos la ruta que lo mostrará:
equipos_services.helloworld:
path: '/equipos/services/helloworld'
defaults:
_form: '\Drupal\equipos_services\Form\HelloWorld'
_title: 'Hello World from services'
requirements:
_permission: 'access content'
3. Fichero services.yml
Llegamos al primer fichero interesante para nuestro objetivo que será el fichero en el que declaremos nuestro servicio:
services:
equipos_services.helloworldservice:
class: Drupal\equipos_services\HelloWorldService
arguments: ['@logger.factory', '@current_user']
En el fichero services.yml será donde declaremos los servicios de nuestro módulo. Para cada servicio necesitaremos declarar la clase que contiene la funcionalidad y será opcional incluir los argumentos que recibirá para el caso que necesite alguno.
Nuestro servicio personalizado necesitará que le pasemos a su vez otros dos servicios:
- logger.factory: Será el servicio que nos permitirá registrar eventos en el log del sistema.
- current_user: Será el servicio que nos permitirá acceder a los datos del usuario actual.
4. HelloWorldInterface.php
Antes de crear la clase que contendrá la lógica de nuestro servicio implementaremos la interface que será la que finalmente utilizaremos cuando inyectamos el servicio en la clase que lo vaya a utililizar, en este caso nuestro formulario de prueba.
<?php
namespace Drupal\equipos_services;
interface HelloWorldInterface {
public function helloWorld();
}
Como podéis ver, la interface de nuestro servicio será muy simple. Solamente declaramos la llamada a una función que devolverá la cadena deseada.
5. HelloWorldService.php
La clase más importante de nuestro ejemplo será la que recoge la lógica de nuestro servicio que además deberá implementar la interface que creamos en el anterior paso.
<?php
namespace Drupal\equipos_services;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Session\AccountProxy;
use Symfony\Component\DependencyInjection\ContainerInterface;
class HelloWorldService implements HelloWorldInterface {
use StringTranslationTrait;
protected $logger;
protected $current_user;
public function __construct(LoggerChannelFactoryInterface $logger, AccountProxy $current_user) {
$this->logger = $logger->get('equipos_services - HelloWorldService');
$this->current_user = $current_user;
}
public static function create(ContainerInterface $container) {
return new static (
$container->get('logger.factory'),
$container->get('current_user'));
}
public function helloWorld() {
$this->logger->info($this->t('[@current_user] HelloWorldService called.',[
'@current_user' => $this->current_user->id()]));
return $this->t('Hello world from HelloWorldService');
}
}
Nuestra función helloWorld simplemente grabará un evento en el log del sistema y devolverá la cadena deseada.
Para poder utilizar la función $this→t() nuestra clase deberá implementar el trait “StringTranslationTrait”.
6. HelloWorld.php
El último paso será la creación del formulario al que inyectaremos nuestro servicio.
<?php
namespace Drupal\equipos_services\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\equipos_services\HelloWorldInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class HelloWorld extends FormBase {
protected $service;
public function __construct(HelloWorldInterface $service) {
$this->service = $service;
}
public static function create (ContainerInterface $container) {
return new static (
$container->get('equipos_services.helloworldservice'));
}
public function getFormId() {
return 'equipos_services_helloworld_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['textfield'] = [
'#type' => 'textfield',
'#title' => $this->t('Test Text'),
'#description' => $this->t('Text loaded from equipos_services.helloworld service'),
'#default_value' => $this->service->helloWorld(),
'#disabled' => TRUE,
];
return $form;
}
public function submitForm(array &$form, FormStateInterface $form_state) { }
}
Como podéis ver en el código, será necesario declarar la interface que implementa la clase de nuestro servicio en la función __construct() y solo nos quedará rescatar nuestro servicio desde el contenedor de servicio en la función estática create().
Nuestro formulario solamente tiene un campo de tipo texto para cuyo valor por defecto utilizaremos la función de nuestro servicio. Si todo ha ido bien cuando accedamos a nuestro formulario también grabaremos un evento en nuestro log.
6. Conclusiones
Con este sencillo ejemplo habremos creado que solamente nos devolverá una cadena de texto, pero que podremos modificar a nuestro antojo para añadir las funciones que creamos oportunas haciéndolo todo lo grande que queramos y que podremos utilizar en nuestro módulos para encapsular funcionalidades globales que serán fácilmente reutilizables por otros módulos.
En las referencias encontraréis un enlace al sandbox de drupal.org que contiene el módulo completo creado para este artículo.
Disfrutar!!!!!
Referencias
https://www.drupal.org/docs/8/api/services-and-dependency-injection/structure-of-a-service-file
https://api.drupal.org/api/drupal/core%21core.services.yml/8.4.x
http://cgit.drupalcode.org/sandbox-javier.martin-2934687/tree/?h=develop