14

I am using the following line in a controller class.

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

Pareview.sh is giving me this error message.

\Drupal calls should be avoided in classes, use dependency injection instead.

How should I accomplish this? Do I need to create a constructor, create a method, or a service? If so, what code should the service need? I found an example on "Drupal calls should be avoided in classes, use dependency injection instead" for a case where a service already exists.

  • create will overload the parent method - here you can inject the services you need. The constructor will then let you assign those to instance variables in the class, so you can use $this->fooInjectedClass->methodName() – Kevin Jan 30 '17 at 16:16
  • Do we already have a question about this? If not, we should really make this a canonical. – mpdonadio Jan 30 '17 at 16:43
20

In a controller you inject services by using the service container. For example 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')
    );  
  }

Then you can avoid \Drupal calls by using the injected service:

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

You can inject any service, existing ones from core/contrib or services you've defined in custom code in a *.services.yml file.

To find a core service name I usually look into core.services.yml, because that's the quickest way when you are working on a drupal project in your IDE.

You can use Drupal Console to list all services, not only from core:

drupal debug:container

You can also use the Devel module, which allows you to search for a name:

/devel/container/service
  • 1
    This sort of question/answer should be expanded upon I agree, and contributed back to drupal.org docs. There is some there, but I feel real world examples like this always help. – Kevin Jan 30 '17 at 17:56
  • 4
    The ControllerBase class already implements the ContainerInjectionInterface interface. There is no need to add implements ContainerInjectionInterface to a class that extends ControllerBase. – kiamlaluno Feb 25 '18 at 15:46
  • Right, just noticed the same thing as @kiamlaluno; would be grand to update the answer! – Stefanos Petrakis Jan 30 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.