"Друпальські дзвінки слід уникати на заняттях, замість цього використовувати ін'єкцію залежності"


16

У моєму модулі, що використовує код нижче, для отримання псевдоніму даного URL:

$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
Інше питання не говорить прямо, як уникнути помилки, яку тут показує ОП. Це швидше запитання від користувача, який хоче підтвердити свій план.
kiamlaluno

Відповіді:


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 фільтрує розмітку, яку ви переносите до нього, як описано в огляді API візуалізації .

  • #markup : Вказує, що масив забезпечує розмітку HTML безпосередньо. Якщо розмітка не дуже проста, наприклад, пояснення в тезі абзацу, зазвичай краще використовувати #theme або #type, щоб тема могла налаштувати розмітку. Зауважте, що значення передається через \Drupal\Component\Utility\Xss::filterAdmin(), яке позбавляє відомі вектори XSS, дозволяючи отримати дозвільний список тегів HTML, які не є векторами XSS. (Тобто, <script>і <style>заборонено.) Перегляньте \Drupal\Component\Utility\Xss::$adminTagsсписок тегів, які будуть дозволені. Якщо для розмітки потрібен будь-який з тегів, які не містяться в цьому списку, ви можете застосувати файл гачок теми та файл шаблонів та / або бібліотеку активів. Крім того, ви можете використовувати ключ масиву візуалізації #allowed_tags, щоб змінити теги, які фільтруються.

  • #allowed_tags : Якщо надано #markup, це можна використовувати для зміни того, які теги використовуються для фільтрування розмітки. Значення має бути масивом тегів, які Xss::filter()приймаються. Якщо встановлено #plain_text, це значення ігнорується.


1
Це мені дуже допомагає. Ін'єкційна залежність працює нормально. :) Дякую.
АРУН

views_embed_view () надає лише масив. Без використання drupal_render () як я можу відображати його як вміст html?
АРУН

Він повертає масив, що передається, який може бути повернутий за допомогою методу контролера, який відображає сторінку.
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, це правильно. ваш код працює ідеально.
АРУН

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.