Nên tránh các cuộc gọi Drupal trong các lớp học, sử dụng tiêm phụ thuộc thay vào đó


16

Trong mô-đun của tôi sử dụng mã dưới đây để nhận bí danh url của url đã cho:

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

Nhưng một cái tôi chạy Đánh giá tự động ( http://pareview.sh/ ) trong mô-đun của tôi, tôi nhận được cảnh báo dưới đây:

16 | CẢNH BÁO | \ Nên tránh các cuộc gọi Drupal trong các lớp học, sử dụng tiêm phụ thuộc thay thế

Làm thế nào tôi có thể cập nhật mã trên bằng cách sử dụng tiêm phụ thuộc? Toàn bộ mã lớp của tôi được đưa ra dưới đây.

<?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
Câu hỏi khác không nói rõ làm thế nào để tránh lỗi mà OP đang hiển thị ở đây. Đó đúng hơn là một câu hỏi được đặt ra từ một người dùng muốn xác nhận về kế hoạch của mình.
kiamlaluno

Câu trả lời:


16

Lấy BlockLibraryControllerlớp làm ví dụ; nó mở rộng cùng lớp với bộ điều khiển của bạn.

Bạn xác định:

  • Một create()phương thức tĩnh và công khai nhận các giá trị từ vùng chứa phụ thuộc và tạo một đối tượng mới của lớp của bạn
  • Một hàm tạo lớp lưu các giá trị được truyền từ phương thức trước đó trong các thuộc tính đối tượng
  • Một tập hợp các thuộc tính đối tượng để lưu các giá trị được truyền trong hàm tạo của lớp

Trong trường hợp của bạn, mã sẽ tương tự như sau.

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

}

Đừng quên đặt use \Drupal\Core\Path\AliasManagerInterface;lên trên cùng của tệp chứa mã bạn đang hiển thị.

Như lưu ý phụ, mã bạn sử dụng để hiển thị chế độ xem là sai: Bạn không cần sử dụng drupal_render()views_embed_view()đã trả về một mảng có thể kết xuất.
Sau đó, mảng kết xuất mà bạn đang trả về có thể không cung cấp đầu ra mà bạn mong đợi. #name có thể sẽ không được sử dụng từ Drupal và #markup lọc đánh dấu mà bạn đang chuyển đến nó, như được mô tả trên tổng quan về API kết xuất .

  • #markup : Chỉ định rằng mảng cung cấp đánh dấu HTML trực tiếp. Trừ khi việc đánh dấu rất đơn giản, chẳng hạn như giải thích trong thẻ đoạn văn, thông thường nên sử dụng #theme hoặc #type thay vào đó, để chủ đề có thể tùy chỉnh đánh dấu. Lưu ý rằng giá trị được truyền qua \Drupal\Component\Utility\Xss::filterAdmin(), loại bỏ các vectơ XSS đã biết trong khi cho phép danh sách các thẻ HTML cho phép không phải là vectơ XSS. (Tức là <script><style>không được phép.) Xem \Drupal\Component\Utility\Xss::$adminTagsdanh sách các thẻ sẽ được cho phép. Nếu đánh dấu của bạn cần bất kỳ thẻ nào không có trong danh sách trắng này, thì bạn có thể triển khai tệp chủ đề và tệp mẫu và / hoặc thư viện tài sản. Ngoài ra, bạn có thể sử dụng khóa mảng kết xuất #allowed_tags để thay đổi các thẻ được lọc.

  • #allowed_tags : Nếu #markup được cung cấp, điều này có thể được sử dụng để thay đổi thẻ nào đang sử dụng để lọc đánh dấu. Giá trị phải là một mảng các thẻ Xss::filter()sẽ chấp nhận. Nếu #plain bản được đặt, giá trị này sẽ bị bỏ qua.


1
Điều này giúp tôi rất nhiều. Phụ thuộc tiêm làm việc tốt. :) Cảm ơn bạn.
ARUN

Views_embed_view () chỉ cung cấp một mảng. Không sử dụng drupal numnder () làm thế nào tôi có thể hiển thị nó dưới dạng nội dung html?
ARUN

Nó trả về một mảng có thể kết xuất, có thể được trả về từ phương thức điều khiển kết xuất một trang.
kiamlaluno

Chỉ cần trả lại những gì views_embed_view()trả lại.
kiamlaluno

bộ điều khiển của tôi đang sử dụng cho một cuộc gọi ajax. nội dung trả về sẽ tự động cập nhật trong trang. Trong khi trả về kết quả của views_embed_view()nó hiển thịArray
ARUN

1

Để sử dụng phép nội xạ phụ thuộc, lớp của bạn cần thực hiện ContainerInjectionInterfacegiao diện. ContainerInjectionInterfacenhiệm vụ mà lớp thực hiện phải có create()phương pháp. Với hàm tạo lớp bổ sung chấp nhận các phụ thuộc được chèn, create()phương thức trả về một thể hiện của lớp của bạn bằng cách chuyển các thể hiện phụ thuộc đã xác định cho lớp của bạn.

Cập nhật: Nó được chỉ ra một cách chính xác bởi @kiamlaluno ContainerInjectionInterfacekhông bắt buộc trong trường hợp này vì ControllerBaseđã thực hiện nó.

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

}

Nó là đủ bạn mở rộng ControllerBase; không cần thiết phải thực hiện ContainerInjectionInterfacevì điều đó đã được thực hiện từ đó ControllerBase.
kiamlaluno

@kiamlaluno, đúng vậy. mã của bạn hoạt động hoàn hảo.
ARUN

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.