Làm cách nào để thay đổi tuyến đường được xác định bởi mô-đun khác?


14

Nói cách khác, Drupl 8 tương đương với hook_menu_alter () là gì?

Drupal 8 vẫn sử dụng hook_menu () , nhưng với những gì tôi có thể thấy, thông tin được trả về bởi hook khác với những gì hook trả về trong Drupal 7. Ví dụ, định nghĩa được đưa ra trong user_menu () cho người dùng là như sau.

  $items['user'] = array(
    'title' => 'User account',
    'title callback' => 'user_menu_title',
    'weight' => -10,
    'route_name' => 'user_page',
    'menu_name' => 'account',
  );

Thuộc tính route_name liên kết đến một mục trong tệp user.routing.yml .

user_page:
  pattern: '/user'
  defaults:
    _content: '\Drupal\user\Controller\UserController::userPage'
  requirements:
    _access: 'TRUE'

Điều này khác với những gì được thực hiện với Symphony và nó làm tôi bối rối về cách một mô-đun có thể thay đổi tuyến đường được xác định từ người dùng khác.

Hàm duy nhất vẫn đang gọi hook_menu_alter()menu_router_build () , nhưng hàm đó vẫn chứa mã cần được cập nhật, vì nó vẫn đang sử dụng hiện không dùng nữa drupal_alter().

  // Alter the menu as defined in modules, keys are like user/%user.
  drupal_alter('menu', $callbacks);
  foreach ($callbacks as $path => $router_item) {
    // If the menu item is a default local task and incorrectly references a
    // route, remove it.
    // @todo This may be removed later depending on the outcome of
    // http://drupal.org/node/1889790
    if (isset($router_item['type']) && $router_item['type'] == MENU_DEFAULT_LOCAL_TASK) {
      unset($callbacks[$path]['route_name']);
    }
    // If the menu item references a route, normalize the route information
    // into the old structure. Note that routes are keyed by name, not path,
    // so the path of the route takes precedence.
    if (isset($router_item['route_name'])) {
      $router_item['page callback'] = 'USES_ROUTE';
      $router_item['access callback'] = TRUE;
      $new_path = _menu_router_translate_route($router_item['route_name']);

      unset($callbacks[$path]);
      $callbacks[$new_path] = $router_item;
    }
  }

Câu trả lời:


6

Xem Thay đổi các tuyến hiện có và thêm các tuyến mới dựa trên các tuyến động ; nó giúp tôi loại bỏ / tìm kiếm được xử lý bởi mô-đun Tìm kiếm. Trong trường hợp của tôi, tôi đã sử dụng mã sau đây.

<?php
/**
 * @file
 * Contains \Drupal\ua_sc_module\Routing\SearchAlterRouteSubscriber.
 */

namespace Drupal\ua_sc_module\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class SearchAlterRouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection) {
    // Remove the /search route.
    $collection->remove('search.view');
  }

}

12

Cho phép các khung nhìn ghi đè các mục định tuyến hiện tại chỉ sử dụng chức năng hiện có.

Nếu bạn muốn thay đổi thông tin được đính kèm trên một tuyến đường, không phải menu, như bộ điều khiển được sử dụng thực tế hoặc các yêu cầu (quyền / vai trò, v.v.), bạn có thể sử dụng một sự kiện do Drupal cung cấp:

  <?php

  use Drupal\Core\Routing\RouteBuildEvent;
  use Drupal\Core\Routing\RoutingEvents;
  use Symfony\Component\EventDispatcher\EventSubscriberInterface;

  class RouteSubscriber implements EventSubscriberInterface {

   /**
    * {@inheritdoc}
    */
   public static function getSubscribedEvents() {
      $events[RoutingEvents::ALTER] = 'alterRoutes';
     return $events;
   }

  /**
   * Alters existing routes.
   *
   * @param \Drupal\Core\Routing\RouteBuildEvent $event
   *   The route building event.
   */
  public function alterRoutes(RouteBuildEvent $event) {
    // Fetch the collection which can be altered.
    $collection = $event->getRouteCollection();
    // The event is fired multiple times so ensure that the user_page route
    // is available.
    if ($route = $collection->get('user_page')) {
      // As example add a new requirement.
      $route->setRequirement('_role', 'anonymous');
    }
  }

  }

Ngoài ra, bạn phải đăng ký một dịch vụ với thẻ 'event_subscacker' cho lớp này.


Có những chi tiết cho việc thiết lập việc đăng ký dịch vụ tại Thay đổi các tuyến đường hiện có và bổ sung thêm các tuyến đường mới dựa trên những động .
colan

7

Vì tôi đã hỏi câu hỏi này, lõi 8 Drupal đã thay đổi và một số vấn đề về các tuyến đường đã được khắc phục.

hook_menu()không được sử dụng từ Drupal 8 nữa; các tuyến đường mà mô-đun sử dụng được xác định trong tệp .routing.yml (ví dụ: user.routing.yml ). Móc thay đổi vẫn được sử dụng, nhưng vì hook_menu()không được sử dụng nữa từ lõi Drupal, nên hook_menu_alter()không được sử dụng.

Các bước cần thiết để thay đổi tuyến đường được xác định từ các mô-đun khác như sau:

  • Xác định một dịch vụ

    services:
      mymodule.route_subscriber:
        class: Drupal\mymodule\Routing\RouteSubscriber
        tags:
          - { name: event_subscriber }
  • Tạo một lớp mở rộng RouteSubscriberBaselớp.

    namespace Drupal\mymodule\Routing;
    
    use Drupal\Core\Routing\RouteSubscriberBase;
    use Symfony\Component\Routing\RouteCollection;
    
    /**
     * Listens to the dynamic route events.
     */
    class RouteSubscriber extends RouteSubscriberBase {
    
      /**
       * {@inheritdoc}
       */
      protected function alterRoutes(RouteCollection $collection) {
        // Change the route associated with the user profile page (/user, /user/{uid}).
        if ($route = $collection->get('user.page')) {
          $route->setDefault('_controller', '\Drupal\mymodule\Controller\UserController::userPage');
        }
      }
    
    }

Lưu ý rằng so với các bản phát hành Drupal 8 trước đó, một số chi tiết được thay đổi.

  • Tên tuyến được đổi từ user_pagethànhuser.page
  • Các yêu cầu cho tuyến đường đó đã thay đổi từ _access: 'TRUE'thành_user_is_logged_in: 'TRUE'
  • Thuộc tính để đặt bộ điều khiển của tuyến đường đã thay đổi từ _contentthành_controller

Nếu bạn muốn khớp nhiều tuyến đường, có cách nào thanh lịch hơn là đặt biến $ khớp thành sai, sau đó lặp qua tất cả chúng cùng một lúc $collection->get()không? Tôi không thể thấy bất kỳ phương pháp rõ ràng.
William Turrell

@WilliamTurrell Bạn có thể lấy một ArrayIteratorđối tượng RouteCollection::getIterator(); điều đó sẽ làm cho việc lặp lại dễ dàng hơn tất cả các mục trong $collection. Bạn cũng có thể nhận được tất cả các tuyến đường trong $collectionvới RouteCollection::all(), mà trả về một mảng.
kiamlaluno
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.