I am trying to restrict access for non admin users on admin/structure/menu so that only admins can create any new links via admin/structure/menu.
Now I want that for one special menu with the ID "Focus" the "Add Link" button is available for another role too.

Here is a Screenshot of the actual backend with the "Add Link" still availabe. I want this to be gone for Hauptnavigation but not for Fokusnavigation. enter image description here

Same thing when you click on a Menu. You get an "Add Link" button. I can disable this with me code below, but I don't know how to allow it for non Admin Roles again. enter image description here

I can get the menu->id() in the my_menu.module file, with the same code like in the routesubscriber below but somehow it doesn't work in the routesubscriber. Drush CR returns an

PHP Fatal error:  Uncaught Error: Call to a member function id() on null in /var/www/html/web/modules/custom/my_menu/src/Routing/RouteSubscriber.php:31                                                                                                                
Stack trace:                                                                                                                                                                                                                                                           
#0 /var/www/html/web/core/lib/Drupal/Core/Routing/RouteSubscriberBase.php(37): Drupal\my_menu\Routing\RouteSubscriber->alterRoutes(Object(Symfony\Component\Routing\RouteCollection))                                                                                  
#1 [internal function]: Drupal\Core\Routing\RouteSubscriberBase->onAlterRoutes(Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))                                              
#2 /var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func(Array, Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#3 /var/www/html/web/core/lib/Drupal/Core/Routing/RouteBuilder.php(189): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...')                                                   
 in /var/www/html/web/modules/custom/my_menu/src/Routing/RouteSubscriber.php on line 31       

Are there other ways to get the value? What am I doing wrong.
Here is my code.


namespace Drupal\my_menu\Routing;

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

 * Class RouteSubscriber
 * hiding menu editing components for non-admins
 * @package Drupal\hw_menu\Routing
class RouteSubscriber extends RouteSubscriberBase {

   * {@inheritdoc}
  public function alterRoutes(RouteCollection $collection) {

    if ($route = $collection->get('entity.menu.add_link_form')) {

  //    dpm($route->getRequirements());

      $menu instanceof \Drupal\system\Entity\Menu;
      $menu = \Drupal::routeMatch()->getParameter('menu');
      if($menu->id() != 'focus') {
        $route->setRequirement('_role', 'administrator');
    //  dpm($route->getRequirements());


   * {@inheritdoc}
  public static function getSubscribedEvents() {
    // Run after content_translation, which has priority -210.
    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -230];
    return $events;

  • Your post isn't very clear. Who are 'they'? What is 'focus'? What are you trying to do? You've shown some code, but not given the clear goal, or even clearly explained what is not working. You've told us how you're trying to do something, and shown code that does something, but you never explained clearly what the end goal is in human terms.
    – Jaypan
    May 13, 2022 at 16:39
  • Sorry, thougt it should be clear by reading the code. Will add further details for humans.
    – macbert
    May 13, 2022 at 16:43
  • I still don't see your actual goal, other than trying to solve some coding issue. But why are you even doing this coding? What is your goal for the front-end user? Without knowing what you want the expected behavior to be, we can't tell you where you're going wrong, we can't even tell you if you are on the right track with your approach, or going the entirely wrong direction altogether. There are 10 ways do do anything in Drupal.
    – Jaypan
    May 13, 2022 at 18:46
  • 4
    Route definitions don't contain parameter values, those are only available when a route is built. The literal answer to what I think your question is, is to add a custom access callback for the route (as described here), but there might be a more robust way to solve the problem if you can edit the question to provide some more context
    – Clive
    May 13, 2022 at 20:54
  • Added some more explanation. I really don't know how to explain it better or even simpler.
    – macbert
    May 16, 2022 at 9:02

1 Answer 1


Would say that you code is failing because there is no menu entity available since the menu parameter converter works when the route gets resolved as commented by @Clive not during route build, which is when the alter event is fired.

On the other hand, why don't you use the Administer menus and menu links permission from core to deny your non-admin user's access to the menu administration? Also you can use Simple Menu Permissions or the Menu Admin per Menu modules if you want more control over your menus.

But if you still want to handle the menu access by yourself you can do that implementing your own access check using the route subscriber you have already.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.