"Le chiamate drupal dovrebbero essere evitate in classe, utilizzare invece l'iniezione di dipendenza"


17

Nel mio modulo usando il codice qui sotto per ottenere l'alias url di dato url:

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

Ma uno che eseguo Revisione automatica ( http://pareview.sh/ ) nel mio modulo sto ricevendo un avviso di seguito:

16 | ATTENZIONE | Le chiamate \ Drupal dovrebbero essere evitate nelle classi, utilizzare invece l'iniezione di dipendenza

Come posso aggiornare il codice sopra usando l'iniezione delle dipendenze? Il mio intero codice di classe è riportato di seguito.

<?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
L'altra domanda non dice esplicitamente come evitare l'errore mostrato dall'OP qui. È piuttosto una domanda fatta da un utente che desidera una conferma del suo piano.
kiamlaluno

Risposte:


16

Prendi la BlockLibraryControllerlezione come esempio; estende la stessa classe del controller.

Tu definisci:

  • Un create()metodo statico e pubblico che ottiene i valori dal contenitore delle dipendenze e crea un nuovo oggetto della classe
  • Un costruttore di classi che salva i valori passati dal metodo precedente nelle proprietà dell'oggetto
  • Un set di proprietà dell'oggetto per salvare i valori passati nel costruttore della classe

Nel tuo caso, il codice sarebbe simile al seguente.

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

}

Non dimenticare di mettere use \Drupal\Core\Path\AliasManagerInterface;in cima al file contenente il codice che stai mostrando.

Come nota a margine , il codice utilizzato per il rendering della vista è errato: non è necessario utilizzarlo drupal_render()perché views_embed_view()restituisce già un array renderizzabile.
Quindi, l'array di rendering che stai restituendo probabilmente non sta dando l'output che ti aspetti. #name probabilmente non verrà usato da Drupal e #markup filtra il markup che ci stai passando, come descritto nella panoramica dell'API di rendering .

  • #markup : specifica che l'array fornisce direttamente il markup HTML. A meno che il markup non sia molto semplice, come una spiegazione in un tag di paragrafo, è preferibile usare invece #theme o #type, in modo che il tema possa personalizzare il markup. Si noti che viene passato il valore \Drupal\Component\Utility\Xss::filterAdmin(), che elimina i vettori XSS noti consentendo un elenco permissivo di tag HTML che non sono vettori XSS. (Vale a dire, <script>e <style>non sono ammessi.) Consulta \Drupal\Component\Utility\Xss::$adminTagsl'elenco dei tag consentiti. Se il markup necessita di uno qualsiasi dei tag che non si trovano in questa whitelist, è possibile implementare un hook a tema e un file modello e / o una libreria di risorse. In alternativa, è possibile utilizzare la chiave dell'array di rendering #allowed_tags per modificare i tag filtrati.

  • #allowed_tags : se viene fornito #markup, questo può essere usato per cambiare quali tag stanno usando per filtrare il markup. Il valore dovrebbe essere una matrice di tag che Xss::filter()accetterebbe. Se #plain_text è impostato, questo valore viene ignorato.


1
Questo mi aiuta molto. Iniezione delle dipendenze che funziona bene. :) Grazie.
ARUN,

views_embed_view () fornisce solo un array. Senza usare drupal_render () come posso visualizzarlo come contenuto html?
ARUN,

Restituisce un array renderizzabile, che può essere restituito dal metodo controller che esegue il rendering di una pagina.
kiamlaluno

Restituisci semplicemente ciò che views_embed_view()ritorna.
kiamlaluno

il mio controller sta usando per una chiamata Ajax. il contenuto restituito verrà aggiornato dinamicamente nella pagina. Mentre restituisce il risultato della views_embed_view()sua visualizzazioneArray
ARUN,

1

Per utilizzare l'iniezione di dipendenza, la tua classe deve implementare l' ContainerInjectionInterfaceinterfaccia. ContainerInjectionInterfaceimpone che la classe di esecuzione debba avere un create()metodo. Con un costruttore di classi aggiuntivo che accetta le dipendenze iniettate, il create()metodo restituisce un'istanza della classe passando le istanze definite delle dipendenze alla classe.

Aggiornamento: è stato giustamente indicato da @kiamlaluno che ContainerInjectionInterfacenon è richiesto in questo caso poiché ControllerBaselo implementa già.

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

}

Basta allungare ControllerBase; non è necessario implementarlo ContainerInjectionInterfacepoiché è già stato fatto da ControllerBase.
kiamlaluno

@kiamlaluno, è corretto. il tuo codice funziona perfettamente.
ARUN,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.