12.15.1. Inyección de dependencias en el controlador
En el artículo anterior analizamos qué es la Inyección de Dependencias (Dependency Injection):
12.15. Servicios e Inyección de Dependencias.
En este artículo se presenta un ejemplo de código con Dependency Injection en un controlador.
/modules/custom/drupalbook/src/Controller/ModalFormContactController.php:
<?php
namespace Drupal\drupalbook\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilder;
/**
* Clase ModalFormContactController.
*/
class ModalFormContactController extends ControllerBase {
/**
* El form builder.
*
* @var \Drupal\Core\Form\FormBuilder
*/
protected $formBuilder;
/**
* Constructor de ModalFormContactController.
*
* @param \Drupal\Core\Form\FormBuilder $form_builder
* El generador de formularios.
*/
public function __construct(FormBuilder $form_builder) {
$this->formBuilder = $form_builder;
}
/**
* {@inheritdoc}
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* El contenedor de servicios de Drupal.
*
* @return static
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('form_builder')
);
}
/**
* Callback para el formulario modal.
*/
public function openModalForm() {
$response = new AjaxResponse();
$modal_form = $this->formBuilder->getForm('Drupal\drupalbook\Form\ModalForm');
$enquiry_title = $this->t("Enviar consulta a @business_name", ['@business_name' => $modal_form['business_name']['#value']]);
$response->addCommand(new OpenModalDialogCommand($enquiry_title, $modal_form));
return $response;
}
}
Analicemos las partes del código relacionadas con DI (Dependency Injection).
namespace Drupal\drupalbook\Controller;
Primero, se especifica el namespace (espacio de nombres), que corresponde a la ubicación del archivo. "drupalbook" es el nombre del módulo.
use Symfony\Component\DependencyInjection\ContainerInterface;
Se importa la clase ContainerInterface, que luego se usará para obtener objetos desde el Service Container.
/**
* El form builder.
*
* @var \Drupal\Core\Form\FormBuilder
*/
protected $formBuilder;
Se declara una propiedad donde se almacenará el objeto proveniente del contenedor. El comentario @var
ayuda al IDE a ofrecer autocompletado para este objeto.
/**
* Constructor de ModalFormContactController.
*
* @param \Drupal\Core\Form\FormBuilder $form_builder
* El form builder.
*/
public function __construct(FormBuilder $form_builder) {
$this->formBuilder = $form_builder;
}
En el constructor, se recibe como parámetro el objeto del Service Container y se guarda en la propiedad $formBuilder
del objeto. Si necesitas más servicios, deberás agregarlos como parámetros adicionales en el constructor. Por ejemplo, si necesitas 10 servicios, el constructor tendrá 10 parámetros.
/**
* {@inheritdoc}
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* El contenedor de servicios de Drupal.
*
* @return static
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('form_builder')
);
}
En el método create()
se accede al objeto del contenedor de servicios y se obtiene el servicio form_builder
, que luego se pasa al constructor y se guarda en la propiedad formBuilder
. Nota: en el contenedor se usa snake_case ($form_builder
), pero en la clase se guarda como camelCase (formBuilder
).
Ahora ya puedes utilizar el servicio inyectado en cualquier método del controlador:
/**
* Callback para el formulario modal.
*/
public function openModalForm() {
...
$modal_form = $this->formBuilder->getForm('Drupal\drupalbook\Form\ModalForm');
...
}