¿Cómo uso la inyección de dependencia en \ Drupal :: moduleHandler () a un controlador?

15

Estoy usando la siguiente línea en una clase de controlador.

    \Drupal::moduleHandler()->alter('mymodule_myfunction', $plugin_items);

Pareview.sh me está dando este mensaje de error.

\ Las llamadas de Drupal deben evitarse en las clases, utilice la inyección de dependencia en su lugar.

¿Cómo debo lograr esto? ¿Necesito crear un constructor, crear un método o un servicio? Si es así, ¿qué código debe necesitar el servicio? Encontré un ejemplo sobre "Las llamadas de Drupal deben evitarse en las clases, use la inyección de dependencia en su lugar" para un caso donde ya existe un servicio.

Kevin Nowaczyk
fuente
createsobrecargará el método principal; aquí puede inyectar los servicios que necesita. El constructor le permitirá asignarlos a las variables de instancia en la clase, para que pueda usar$this->fooInjectedClass->methodName()
Kevin
¿Ya tenemos una pregunta sobre esto? Si no, realmente deberíamos hacer de esto un canónico.
mpdonadio

Respuestas:

21

En un controlador, inyecta servicios utilizando el contenedor de servicios. Por ejemplo ModuleHandler:

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;

class MyController extends ControllerBase {

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs a MyController object
   *
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler service.
   */
  public function __construct(ModuleHandlerInterface $module_handler) {
    $this->moduleHandler = $module_handler;
  }

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

Entonces puedes evitar \Drupal llamadas utilizando el servicio inyectado:

$this->moduleHandler->alter('mymodule_myfunction', $plugin_items);

Puede inyectar cualquier servicio, los existentes desde el núcleo / contrib o los servicios que ha definido en un código personalizado en un *.services.ymlarchivo.

Para encontrar un nombre de servicio principal, generalmente busco core.services.yml , porque esa es la forma más rápida cuando está trabajando en un proyecto drupal en su IDE.

Puede usar la Consola Drupal para enumerar todos los servicios, no solo desde el núcleo:

drupal debug:container

También puede usar el módulo Devel , que le permite buscar un nombre:

/devel/container/service
4k4
fuente
1
Este tipo de pregunta / respuesta debe ampliarse si estoy de acuerdo, y contribuir de nuevo a los documentos de drupal.org. Hay algunos allí, pero siento que ejemplos del mundo real como este siempre ayudan.
Kevin
44
La ControllerBaseclase ya implementa la ContainerInjectionInterfaceinterfaz. No es necesario agregar implements ContainerInjectionInterfacea una clase que se extiende ControllerBase.
kiamlaluno
Bien, acabo de notar lo mismo que @kiamlaluno; sería grandioso actualizar la respuesta!
Stefanos Petrakis