"Chamadas de Drupal devem ser evitadas nas classes; use injeção de dependência"

17

No meu módulo, usando o código abaixo para obter o alias de URL de um determinado URL:

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

Mas eu executo a Revisão automatizada ( http://pareview.sh/ ) no meu módulo e estou recebendo o aviso abaixo:

16 ATENÇÃO | \ Chamadas de Drupal devem ser evitadas nas classes, use a injeção de dependência em vez disso

Como posso atualizar o código acima usando injeção de dependência? Meu código de turma inteiro é fornecido abaixo.

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

}
UMA CORRIDA
fonte
1
A outra pergunta não diz expressamente como evitar o erro que o OP está mostrando aqui. É uma pergunta feita por um usuário que deseja confirmar seu plano.
Kiamlaluno

Respostas:

16

Tome a BlockLibraryControllerclasse como exemplo; estende a mesma classe que seu controlador.

Você define:

  • Um create()método estático e público que obtém os valores do contêiner de dependência e cria um novo objeto da sua classe
  • Um construtor de classe que salva os valores passados ​​do método anterior nas propriedades do objeto
  • Um conjunto de propriedades do objeto para salvar os valores passados ​​no construtor da classe

No seu caso, o código seria semelhante ao seguinte.

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

}

Não se esqueça de colocar use \Drupal\Core\Path\AliasManagerInterface;na parte superior do arquivo que contém o código que você está mostrando.

Como observação lateral, o código que você usa para renderizar a exibição está errado: você não precisa usá-lo drupal_render()porque views_embed_view()já retorna uma matriz renderizável.
Então, a matriz de renderização que você está retornando provavelmente não está dando a saída que você espera. #name provavelmente não será usado no Drupal e #markup filtra a marcação que você está passando, conforme descrito na visão geral da API de renderização .

  • #markup : especifica que a matriz fornece marcação HTML diretamente. A menos que a marcação seja muito simples, como uma explicação em uma tag de parágrafo, normalmente é preferível usar #theme ou #type, para que o tema possa personalizar a marcação. Observe que o valor é passado \Drupal\Component\Utility\Xss::filterAdmin(), que retira os vetores XSS conhecidos, permitindo uma lista permissiva de tags HTML que não são vetores XSS. (Ou seja, <script>e <style>não são permitidos.) Consulte \Drupal\Component\Utility\Xss::$adminTagsa lista de tags que serão permitidas. Se sua marcação precisar de alguma das tags que não estão nessa lista de permissões, você poderá implementar um gancho de tema e um arquivo de modelo e / ou uma biblioteca de ativos. Como alternativa, você pode usar a chave da matriz de renderização #allowed_tags para alterar quais tags são filtradas.

  • #allowed_tags : se #markup for fornecido, isso poderá ser usado para alterar quais tags estão sendo usadas para filtrar a marcação. O valor deve ser uma matriz de tags que Xss::filter()aceitaria. Se #plain_text estiver definido, esse valor será ignorado.

kiamlaluno
fonte
1
Isto me ajuda muito. Injeção de dependência funcionando bem. :) Obrigado.
ARUN
views_embed_view () apenas fornecendo uma matriz. Sem usar drupal_render (), como posso exibi-lo como conteúdo html?
ARUN
Ele retorna uma matriz renderizável, que pode ser retornada pelo método do controlador que renderiza uma página.
Kiamlaluno
Apenas devolva o que views_embed_view() retorna.
Kiamlaluno
meu controlador está usando para uma chamada ajax. o conteúdo retornado será atualizado na página dinamicamente. Enquanto retornar o resultado deviews_embed_view() exibiçãoArray
ARUN
1

Para utilizar a injeção de dependência, sua classe precisa implementar a ContainerInjectionInterfaceinterface. ContainerInjectionInterfaceexige que a classe de implementação tenha que ter create()método. Com o construtor de classe adicional que aceita as dependências injetadas, o create()método retorna uma instância da sua classe passando as instâncias definidas das dependências para a sua classe.

Atualização: foi justamente apontado pelo @kiamlaluno que ContainerInjectionInterfacenão é necessário neste caso, pois ControllerBasejá o implementa.

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

}
maijs
fonte
É o suficiente para você estender ControllerBase; não é necessário implementar, ContainerInjectionInterfacepois isso já foi feito ControllerBase.
kiamlaluno
@kiamlaluno, isso está correto. seu código funciona perfeito.
ARUN