16

In my module using below code for getting url alias of given url:

$alias = \Drupal::service('path.alias_manager')->getPathByAlias($_POST['url']);

But one I run Automated Review(http://pareview.sh/) in my module I am getting below warning:

16 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead

How can I update above code using dependency injection? My entire class code is given below.

<?php

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * MyModule Class defines ajax callback function.
 */
class MyModule extends ControllerBase {
/**
 * Callback function for ajax request.
 */

  public function getUserContent() {
    $alias = \Drupal::service('path.alias_manager')->getPathByAlias($_POST['url']);
    $alias = explode('/', $alias);
    $my_module_views = views_embed_view('my_module', 'default', $alias[2]);
    $my_module= drupal_render($my_module_views);
    return array(
      '#name' => 'my_module_content',
      '#markup' => '<div class="my_module_content">' . $my_module. '</div>',
    );
  }

}
16

Take the BlockLibraryController class as example; it extends the same class as your controller.

You define:

  • A static and public create() method that gets the values from the dependency container, and creates a new object of your class
  • A class constructor that saves the values passed from the previous method in object properties
  • A set of object properties to save the values passed in the class constructor

In your case, the code would be similar to the following one.

class MyModuleController extends ControllerBase {
  /**
   * The path alias manager.
   *
   * @var \Drupal\Core\Path\AliasManagerInterface
   */
  protected aliasManager;

  /**
   * Constructs a MyModuleController object.
   *
   * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
   *   The path alias manager.
   */
  public function __construct(AliasManagerInterface $alias_manager) {
    $this->aliasManager = $alias_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('path.alias_manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getUserContent() {
    $alias = $this->aliasManager->getPathByAlias($_POST['url']);
    // Omissis.
  }

}

Don't forget to put use \Drupal\Core\Path\AliasManagerInterface; on the top of the file containing the code you are showing.

As side note, the code you use to render the view is wrong: You don't need to use drupal_render() because views_embed_view() already returns a renderable array.
Then, the render array you are returning is probably not giving the output you expect. #name is probably not going to be used from Drupal, and #markup filters the markup you are passing to it, as described on Render API overview.

  • #markup: Specifies that the array provides HTML markup directly. Unless the markup is very simple, such as an explanation in a paragraph tag, it is normally preferable to use #theme or #type instead, so that the theme can customize the markup. Note that the value is passed through \Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS vectors while allowing a permissive list of HTML tags that are not XSS vectors. (I.e, <script> and <style> are not allowed.) See \Drupal\Component\Utility\Xss::$adminTags for the list of tags that will be allowed. If your markup needs any of the tags that are not in this whitelist, then you can implement a theme hook and template file and/or an asset library. Alternatively, you can use the render array key #allowed_tags to alter which tags are filtered.

  • #allowed_tags: If #markup is supplied this can be used to change which tags are using to filter the markup. The value should be an array of tags that Xss::filter() would accept. If #plain_text is set this value is ignored.

  • 1
    This helps me a lot. Dependency injection working fine. :) Thank you. – ARUN Jul 15 '16 at 8:11
  • views_embed_view() only providing an array. Without using drupal_render() how can I display it as html content? – ARUN Jul 15 '16 at 8:16
  • It returns a renderable array, which can be returned from the controller method that renders a page. – kiamlaluno Jul 15 '16 at 8:18
  • Just return what views_embed_view() returns. – kiamlaluno Jul 15 '16 at 8:19
  • my controller is using for a ajax call. the returned content will update in the page dynamically. While return the result of views_embed_view() it showing Array – ARUN Jul 15 '16 at 8:20
1

In order to utilize dependency injection, your class needs to implement ContainerInjectionInterface interface. ContainerInjectionInterface mandates that implementing class has to have create() method. With additional class constructor which accepts the injected dependencies, create() method returns an instance of your class by passing the defined instances of dependencies to your class.

Update: It was rightfully pointed by @kiamlaluno that ContainerInjectionInterface is not required in this case since ControllerBase already implements it.

<?php

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Path\AliasManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * MyModule Class defines ajax callback function.
 */
class MyModule extends ControllerBase {

  /** @var \Drupal\Core\Path\AliasManagerInterface $aliasManager */
  protected $aliasManager;

  /**
   * MyModule constructor.
   *
   * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager
   */
  public function __construct(AliasManagerInterface $alias_manager) {
    $this->aliasManager = $alias_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('path.alias_manager')
    );
  }

  /**
   * Callback function for ajax request.
   */
  public function getUserContent() {
    $alias = $this->aliasManager->getPathByAlias($_POST['url']);
    // Your code.
  }

}
  • It is enough you extend ControllerBase; it is not necessary to implement ContainerInjectionInterface since that is already done from ControllerBase. – kiamlaluno Jul 15 '16 at 8:07
  • @kiamlaluno, that is correct. your code works perfect. – ARUN Jul 15 '16 at 8:13
0

It is other for to solve the problem. https://www.previousnext.com.au/blog/injecting-dependencies-into-drupal-8-plugins

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.