Como uso a injeção de dependência em \ Drupal :: moduleHandler () em um Controller?

15

Estou usando a seguinte linha em uma classe de controlador.

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

Pareview.sh está me dando essa mensagem de erro.

\ Chamadas de Drupal devem ser evitadas nas classes, use a injeção de dependência.

Como devo fazer isso? Preciso criar um construtor, criar um método ou um serviço? Em caso afirmativo, qual código o serviço precisa? Eu encontrei um exemplo em "Chamadas Drupal devem ser evitadas nas classes, use a injeção de dependência" para um caso em que já exista um serviço.

Kevin Nowaczyk
fonte
createsobrecarregará o método pai - aqui você pode injetar os serviços necessários. O construtor, então, permitem atribuir os a variáveis de instância na classe, assim você pode usar$this->fooInjectedClass->methodName()
Kevin
Já temos uma pergunta sobre isso? Caso contrário, deveríamos realmente tornar isso canônico.
mpdonadio

Respostas:

21

Em um controlador, você injeta serviços usando o contêiner de serviço. Por exemplo 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')
    );  
  }

Em seguida, você pode evitar \Drupalchamadas usando o serviço injetado:

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

Você pode injetar qualquer serviço, existente do núcleo / contrib ou serviços que você definiu no código personalizado em um *.services.ymlarquivo.

Para encontrar um nome de serviço principal, costumo procurar core.services.yml, porque essa é a maneira mais rápida quando você está trabalhando em um projeto drupal no seu IDE.

Você pode usar o Drupal Console para listar todos os serviços, não apenas do núcleo:

drupal debug:container

Você também pode usar o módulo Devel , que permite procurar um nome:

/devel/container/service
4k4
fonte
1
Esse tipo de pergunta / resposta deve ser expandido quando eu concordo e contribuído de volta para os documentos do drupal.org. Existem alguns lá, mas acho que exemplos do mundo real sempre ajudam.
Kevin
4
A ControllerBaseclasse já implementa a ContainerInjectionInterfaceinterface. Não há necessidade de adicionar implements ContainerInjectionInterfacea uma classe que se estende ControllerBase.
kiamlaluno
Certo, apenas notei a mesma coisa que @kiamlaluno; seria ótimo atualizar a resposta!
Stefanos Petrakis