“应该避免在类中进行重复调用,而应使用依赖注入”


16

在我的模块中,使用以下代码获取给定网址的网址别名:

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

但是我在我的模块中运行“自动审阅”(http://pareview.sh/)时,我得到以下警告:

16 | 警告| \在类中应避免重复调用,而应使用依赖注入

如何使用依赖注入来更新以上代码?我的整个课程代码如下。

<?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>',
    );
  }

}


1
另一个问题没有明确说明如何避免OP在此处显示的错误。这是由想要确认其计划的用户提出的问题。
kiamlaluno

Answers:


16

BlockLibraryController班级为例;它扩展了与您的控制器相同的类。

您定义:

  • 一个静态的公共create()方法,该方法从依赖项容器中获取值,并创建类的新对象
  • 一个类构造函数,它将从先前方法传递的值保存在对象属性中
  • 一组对象属性,用于保存在类构造函数中传递的值

在您的情况下,代码将类似于以下代码。

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.
  }

}

不要忘记将use \Drupal\Core\Path\AliasManagerInterface;包含正在显示的代码的文件放在顶部。

附带说明,用于渲染视图的代码是错误的:不需要使用,drupal_render()因为views_embed_view()已经返回了可渲染数组。
然后,您要返回的渲染数组可能没有提供您期望的输出。#name可能不会在Drupal中使用,并且#markup过滤您传递给它的标记,如Render API概述中所述

  • #markup:指定数组直接提供HTML标记。除非标记非常简单(例如在段落标记中的解释),否则通常最好使用#theme或#type,以便主题可以自定义标记。请注意,该值是通过传递的\Drupal\Component\Utility\Xss::filterAdmin(),它会剥离已知的XSS向量,同时允许不是XSS向量的HTML标签的允许列表。(即,<script>并且<style>是不允许的。)请参阅参考资料\Drupal\Component\Utility\Xss::$adminTags,以获取允许的标签列表。如果您的标记需要此白名单中没有的任何标记,则可以实现主题挂钩和模板文件和/或资产库。另外,您可以使用渲染数组键#allowed_tags更改要过滤的标签。

  • #allowed_tags:如果提供了#markup,则可用于更改用于过滤标记的标签。该值应该是Xss::filter()可以接受的标签数组。如果设置了#plain_text,则将忽略此值。


1
这对我有很大帮助。依赖注入工作正常。:) 谢谢。
2016年

views_embed_view()仅提供一个数组。如果不使用drupal_render(),如何将其显示为html内容?
2016年

它返回一个可渲染的数组,可以从渲染页面的controller方法中返回该数组。
kiamlaluno

只返回返回的内容views_embed_view()
kiamlaluno

我的控制器正在使用ajax调用。返回的内容将在页面中动态更新。虽然返回的结果,views_embed_view()它显示Array
ARUN

1

为了利用依赖注入,您的类需要实现ContainerInjectionInterface接口。ContainerInjectionInterface要求实现类必须具有create()方法。使用其他接受注入的依赖项的类构造函数,create()方法通过将已定义的依赖项实例传递给您的类来返回您的类的实例。

更新: @kiamlaluno正确指出,ContainerInjectionInterface在这种情况下,由于ControllerBase已经实现了它,因此不需要。

<?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.
  }

}

您扩展就足够了ControllerBase;无需实施,ContainerInjectionInterface因为该操作已从中完成ControllerBase
kiamlaluno

@kiamlaluno,是正确的。您的代码工作完美。
2016年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.