Come posso usare l'iniezione delle dipendenze su \ Drupal :: moduleHandler () su un controller?


15

Sto usando la seguente riga in una classe di controller.

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

Pareview.sh mi sta dando questo messaggio di errore.

\ Le chiamate Drupal dovrebbero essere evitate nelle classi, utilizzare invece l'iniezione di dipendenza.

Come dovrei farlo? Devo creare un costruttore, creare un metodo o un servizio? In tal caso, quale codice dovrebbe essere necessario al servizio? Ho trovato un esempio su "Le chiamate Drupal dovrebbero essere evitate nelle classi, utilizzare invece l'iniezione di dipendenza" per un caso in cui esiste già un servizio.


createsovraccaricherà il metodo genitore - qui puoi iniettare i servizi di cui hai bisogno. Il costruttore ti consentirà quindi di assegnarle a variabili di istanza nella classe, in modo da poterle utilizzare$this->fooInjectedClass->methodName()
Kevin

Abbiamo già una domanda al riguardo? In caso contrario, dovremmo davvero renderlo un canonico.
mpdonadio

Risposte:


21

In un controller si iniettano servizi utilizzando il contenitore dei servizi. Per esempio 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')
    );  
  }

Quindi è possibile evitare le \Drupalchiamate utilizzando il servizio iniettato:

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

Puoi iniettare qualsiasi servizio, quelli esistenti da core / contrib o servizi che hai definito nel codice personalizzato in un *.services.ymlfile.

Per trovare un nome di servizio di base che di solito cerco core.services.yml, perché è il modo più rapido quando si lavora su un progetto drupal nel proprio IDE.

Puoi utilizzare Drupal Console per elencare tutti i servizi, non solo dal core:

drupal debug:container

Puoi anche usare il modulo Devel , che ti permette di cercare un nome:

/devel/container/service

1
Questo tipo di domanda / risposta dovrebbe essere ampliato e concordo con i documenti di drupal.org. Ce ne sono alcuni lì, ma sento che esempi del mondo reale come questo aiutano sempre.
Kevin

4
La ControllerBaseclasse implementa già l' ContainerInjectionInterfaceinterfaccia. Non è necessario aggiungere implements ContainerInjectionInterfacea una classe che si estende ControllerBase.
kiamlaluno

Bene, ho appena notato la stessa cosa di @kiamlaluno; sarebbe grandioso aggiornare la risposta!
Stefanos Petrakis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.