Как я могу использовать внедрение зависимости \ Drupal :: moduleHandler () в контроллер?

15

Я использую следующую строку в классе контроллера.

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

Pareview.sh дает мне это сообщение об ошибке.

В классах следует избегать вызовов Drupal, вместо этого используйте внедрение зависимостей.

Как мне это сделать? Нужно ли создавать конструктор, метод или сервис? Если да, то какой код нужен сервису? Я нашел пример: «В классах следует избегать вызовов Drupal, вместо этого используйте внедрение зависимостей» для случая, когда сервис уже существует.

Кевин Новачик
источник
createперегрузит родительский метод - здесь вы можете ввести нужные вам сервисы. Затем конструктор позволит вам назначить их переменным экземпляра в классе, чтобы вы могли их использовать$this->fooInjectedClass->methodName()
Кевин,
У нас уже есть вопрос по этому поводу? Если нет, мы действительно должны сделать это каноническим.
mpdonadio

Ответы:

21

В контроллере вы вводите сервисы, используя сервисный контейнер. Например 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')
    );  
  }

Тогда вы можете избежать \Drupalзвонков, используя услугу:

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

Вы можете внедрить в *.services.ymlфайл любую службу, существующую из core / contrib или службы, которые вы определили в пользовательском коде .

Чтобы найти имя основного сервиса, я обычно смотрю core.services.yml, потому что это самый быстрый способ, когда вы работаете над проектом drupal в вашей IDE.

Вы можете использовать консоль Drupal для вывода списка всех сервисов, а не только из ядра:

drupal debug:container

Вы также можете использовать модуль Devel , который позволяет искать имя:

/devel/container/service
4k4
источник
1
Подобные вопросы и ответы должны быть расширены после того, как я согласен, и отправлены обратно в документы drupal.org. Там есть некоторые , но я чувствую, что примеры из реального мира, такие как это, всегда помогают.
Кевин
4
ControllerBaseКласс уже реализует ContainerInjectionInterfaceинтерфейс. Нет необходимости добавлять implements ContainerInjectionInterfaceв класс, который расширяется ControllerBase.
kiamlaluno
Точно, просто заметил то же самое, что и @kiamlaluno; было бы здорово обновить ответ!
Стефанос Петракис