言い換えれば、Drupal 8は hook_menu_alter() と同等ですか?
Drupal 8は引き続きhook_menu()
を使用しますが、私が見ることができるように、フックによって返される情報は、フックがDrupal 7で返すものとは異なります。たとえば、 user_menu()
でユーザーに与えられるのは次のとおりです。
_ $items['user'] = array(
'title' => 'User account',
'title callback' => 'user_menu_title',
'weight' => -10,
'route_name' => 'user_page',
'menu_name' => 'account',
);
_
Route_nameプロパティは ser.routing.yml ファイルのエントリにリンクしています。
_user_page:
pattern: '/user'
defaults:
_content: '\Drupal\user\Controller\UserController::userPage'
requirements:
_access: 'TRUE'
_
これはSymphonyで行ったこととは異なり、モジュールが別のユーザーから定義されたルートをどのように変更できるかについて混乱します。
hook_menu_alter()
を呼び出している唯一の関数はmenu_router_build()
ですが、その関数には、非推奨の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;
}
}
_
動的ルートに基づいて既存のルートを変更し、新しいルートを追加する を参照検索モジュールによって処理された/ searchを削除することは、私にとってはうまくいきました。私の場合、次のコードを使用しました。
<?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');
}
}
ビューが既存のルーティングアイテムを上書きできるようにします は既存の機能を使用します。
ルートではなく、実際に使用されているコントローラーなどのルートに添付されている情報や要件(権限/役割など)を変更する場合は、Drupalが提供するイベントを使用できます。
<?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');
}
}
}
さらに、このクラスのタグ「event_subscriber」でサービスを登録する必要があります。
私がこの質問をしたので、Drupal 8コアが変更され、ルートに関するいくつかの問題が修正されました。
Drupal 8からはhook_menu()
は使用されなくなりました。モジュールが使用するルートは.routing.ymlファイルで定義されます(例 ser.routing.yml) )。変更フックは引き続き使用されますが、hook_menu()
はもう使用されないため、Drupalコアから、Drupalコアは使用しませんhook_menu_alter()
も呼び出します。
他のモジュールから定義されたルートを変更するために必要な手順は次のとおりです。
event_subscriberとしてタグ付けされたサービスを定義します(タグは重要な部分です。そうでない場合、サービスは期待どおりに動作しません。)
services:
mymodule.route_subscriber:
class: Drupal\mymodule\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
RouteSubscriberBase
クラスを拡張するクラスを作成します。
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');
}
}
}
以前のDrupal 8リリースと比較して、一部の詳細が変更されていることに注意してください。
_access: 'TRUE'
から_user_is_logged_in: 'TRUE'
に変更されました