Jak użyć wstrzykiwania zależności w \ Drupal :: moduleHandler () do kontrolera?

15

Korzystam z następującego wiersza w klasie kontrolera.

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

Pareview.sh wyświetla mi ten komunikat o błędzie.

\ Wywołania Drupala należy unikać w klasach, zamiast tego należy stosować wstrzykiwanie zależności.

Jak mam to osiągnąć? Czy muszę utworzyć konstruktor, metodę lub usługę? Jeśli tak, jakiego kodu powinna potrzebować usługa? Znalazłem przykład dotyczący „wywołań Drupala w klasach, zamiast tego używaj wstrzykiwania zależności” w przypadku, gdy usługa już istnieje.

Kevin Nowaczyk
źródło
createprzeciążą metodę nadrzędną - tutaj możesz wstrzyknąć potrzebne usługi. Konstruktor pozwoli ci następnie przypisać je do zmiennych instancji w klasie, abyś mógł użyć$this->fooInjectedClass->methodName()
Kevin
Czy mamy już pytanie na ten temat? Jeśli nie, powinniśmy naprawdę uczynić to kanonicznym.
mpdonadio

Odpowiedzi:

21

W kontrolerze wstrzykujesz usługi za pomocą kontenera usług. Na przykład 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')
    );  
  }

Następnie możesz uniknąć \Drupalpołączeń za pomocą wstrzykniętej usługi:

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

Możesz wstrzyknąć dowolną usługę, istniejącą z core / contrib lub usługi zdefiniowane w niestandardowym kodzie w *.services.ymlpliku.

Aby znaleźć podstawową nazwę usługi, zwykle szukam core.services.yml, ponieważ jest to najszybszy sposób, gdy pracujesz nad projektem drupal w twoim IDE.

Możesz użyć Drupal Console, aby wyświetlić listę wszystkich usług, nie tylko podstawowych:

drupal debug:container

Możesz także użyć modułu Devel , który pozwala wyszukać nazwę:

/devel/container/service
4k4
źródło
1
Tego rodzaju pytania / odpowiedzi powinny zostać rozszerzone, jeśli się zgadzam, i wróciły do ​​dokumentów drupal.org. Jest ich trochę , ale czuję, że takie przykłady ze świata rzeczywistego zawsze pomagają.
Kevin
4
ControllerBaseKlasa już implementuje ContainerInjectionInterfaceinterfejs. Nie ma potrzeby dodawania implements ContainerInjectionInterfacedo rozszerzonej klasy ControllerBase.
kiamlaluno
Właśnie zauważyłem to samo, co @kiamlaluno; byłoby wspaniale zaktualizować odpowiedź!
Stefanos Petrakis