I have been trying to disable a menu item "standard.front_page" using the following code:

db_query("UPDATE {menu_tree} SET enabled = 0 WHERE id LIKE 'standard.front_page';");
db_query("DELETE FROM {cache_menu};");

It works fine till I do a cache rebuild using drush cr. Once I do a cache rebuild the menu item again comes back.

Can anyone please suggest a good way of doing the above?

  • What are you actually trying to accomplish? – mradcliffe Jun 21 '16 at 17:07
  • 2
    Tip: using db queries to change behaviors like that is not recommended because it bypasses the framework. – Eyal Jun 21 '16 at 19:53
  • 1
    You will probably need to implement an alter hook or an event subscriber service. – Eyal Jun 21 '16 at 19:55
  • What would be a suggested way of doing it. – GeekTantra Jun 22 '16 at 9:06

You can retrieve the Drupal menu link & cache services to programmatically change the menu link status. Something like this example function:

function menu_state_toggle($menu_id, $enabled = TRUE) {
  $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
  $front_page_link = $menu_link_manager->getDefinition($menu_id);
  $front_page_link['enabled'] = $enabled ? 1 : 0; 
  $menu_link_manager->updateDefinition($menu_id, $front_page_link);
  $cache = \Drupal::cache('menu');

menu_state_toggle('standard.front_page', FALSE);
| improve this answer | |
  • 1
    $enabled ? 1 : 0 can just be replaced with (int) $enabled. – kiamlaluno Dec 17 '17 at 17:01

As a post-migrate cleanup step, I needed to remove a few nominated items from our main menu. Other settings (views, imported via config management) were going to take over the role that used to be static pages. Here is how it went:

 * Startup changes for upgrading from the migrated base site to D8 version.
function drupalorgnz_upgrade_install() {
  // From the base upgrade, remove the static pages that were in the main menu
  // as they were replaced with proper views pages.
  // The 'pages' still exist, and are used as intro text blocks in the
  // news views blocks,
  // but relinquish their menu items and paths.
  // Zap the legacy /companies and /showcases nodes.
  $old_nids = [517,518];
  foreach ($old_nids as $nid) {
    $node = \Drupal\node\Entity\Node::load($nid);
    // Zap out the path_alias and the menu item to anonymize this node.

    // That was easy.
    // Next hugely trickier.
    // This is BS. Eventually found the method in menu_ui_node_predelete()
    /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
    $result = $menu_link_manager->loadLinksByRoute('entity.node.canonical', ['node' => $node->id()]);
    if (!empty($result)) {
      foreach ($result as $id => $instance) {
        if ($instance->isDeletable() && strpos($id, 'menu_link_content:') === 0) {
| improve this answer | |

Drupal 8: If you simply want to disable a link but still have it show on the menu use the following in the link path on the menu item.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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