Bagaimana cara menggunakan injeksi dependensi pada \ Drupal :: moduleHandler () ke Controller?

15

Saya menggunakan baris berikut di kelas controller.

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

Pareview.sh memberi saya pesan kesalahan ini.

\ Panggilan Drupal harus dihindari di kelas, gunakan injeksi ketergantungan sebagai gantinya.

Bagaimana saya harus mencapai ini? Apakah saya perlu membuat konstruktor, membuat metode, atau layanan? Jika demikian, kode apa yang harus layanan butuhkan? Saya menemukan contoh pada "Panggilan Drupal harus dihindari di kelas, gunakan injeksi ketergantungan sebagai gantinya" untuk kasus di mana layanan sudah ada.

Kevin Nowaczyk
sumber
createakan membebani metode induk - di sini Anda dapat menyuntikkan layanan yang Anda butuhkan. Konstruktor kemudian akan membiarkan Anda menetapkan mereka ke variabel instan di kelas, sehingga Anda dapat menggunakan$this->fooInjectedClass->methodName()
Kevin
Apakah kita sudah memiliki pertanyaan tentang ini? Jika tidak, kita harus benar-benar menjadikan ini kanonik.
mpdonadio

Jawaban:

21

Dalam pengontrol Anda menyuntikkan layanan dengan menggunakan wadah layanan. Sebagai contoh 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')
    );  
  }

Maka Anda dapat menghindari \Drupalpanggilan dengan menggunakan layanan yang disuntikkan:

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

Anda dapat menyuntikkan layanan apa pun, yang ada dari inti / contrib atau layanan yang Anda tetapkan dalam kode khusus dalam *.services.ymlfile.

Untuk menemukan nama layanan inti yang biasa saya lihat core.services.yml, karena itulah cara tercepat ketika Anda mengerjakan proyek drupal di IDE Anda.

Anda dapat menggunakan Konsol Drupal untuk mendaftar semua layanan, tidak hanya dari inti:

drupal debug:container

Anda juga dapat menggunakan modul Devel , yang memungkinkan Anda mencari nama:

/devel/container/service
4k4
sumber
1
Pertanyaan / jawaban semacam ini harus diperluas setelah saya setuju, dan berkontribusi kembali ke drupal.org docs. Ada beberapa di sana, tetapi saya merasakan contoh dunia nyata seperti ini selalu membantu.
Kevin
4
The ControllerBasekelas sudah mengimplementasikan ContainerInjectionInterfaceinterface. Tidak perlu menambahkan implements ContainerInjectionInterfaceke kelas yang diperluas ControllerBase.
kiamlaluno
Benar, hanya memperhatikan hal yang sama dengan @kiamlaluno; akan bagus untuk memperbarui jawabannya!
Stefanos Petrakis