1

How can I automatically create a menu link for a new node in Drupal 8?

2 Answers 2

1

You can use a deriver class for this.

In your foo.links.menu.yml file

entity.node.canonical:
  deriver: '\Drupal\foo\Plugin\Deriver\FooMenuLinkDeriver'
  route_name: entity.node.canonical

In Drupal\foo\Plugin\Deriver\FooMenuLinkDeriver

class FooMenuLinkDeriver extends DeriverBase implements ContainerDeriverInterface {
  public function getDerivativeDefinitions($base) {
    $plugin_definitions = [];
    foreach (Node::loadMultiple() as $nid => $node) {
      $plugin_definitions[$nid] = $base;
      $plugin_definitions[$nid]['route_parameters']['node'] = $nid;
      $plugin_definitions[$nid]['title'] = $node->label();
    }
    return $plugin_definitions; 
  }
0

As far as I know you will need a custom module implementing hook_entity_presave or hook_entity_insert

hook_entity_insert would be called only when a NEW node is created hook_entity_presave would be called any time a node is saved/updated

<?php
use \Drupal\Core\Entity\EntityInterface;
use \Drupal\menu_link_content\Entity\MenuLinkContent;

function MODULE_NAME_entity_insert(EntityInterface $entity){

    if ($entity->getEntityType()->id() == 'node') {    
        $title = $entity->getTitle();
        //OR
        //$title = $entity->title->value;
        $nid = $entity->id();

        $menu_link = MenuLinkContent::create([
          'title' => $title,
          'link' => ['uri' => 'internal:/node/' . $nid],
          'menu_name' => 'main',
          'expanded' => TRUE,
        ]);
        $menu_link->save();
    }
}
?>

If you use hook_entity_presave you might need to check whether the MENU item exists otherwise you will end up with a new menu item each time the node is updated.

<?php
use \Drupal\Core\Entity\EntityInterface;
use \Drupal\menu_link_content\Entity\MenuLinkContent;

function MODULE_NAME_entity_presave(EntityInterface $entity){

    if ($entity->getEntityType()->id() == 'node') {    
        $title = $entity->getTitle();
        //OR
        //$title = $entity->title->value;
        $nid = $entity->id();           

        $menu_link_manager = \Drupal::service('plugin.manager.menu.link');

        $menu_links = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $nid));
        if(sizeof($menu_links)){
            foreach ($menu_links as $menu_link) {
                $definition = $menu_link->getPluginDefinition();
                $definition['title'] = $title;
                $menu_link_manager->updateDefinition($menu_link->getPluginId(), $definition);
                //PHP warning pending fix https://www.drupal.org/node/2775665
            }
        }else{
            $menu_link = MenuLinkContent::create([
                'title' => $title,
                'link' => ['uri' => 'internal:/node/' . $nid],
                'menu_name' => 'main',
                'expanded' => TRUE,
            ]);
            $menu_link->save();
        }
    }
}

To get the basic of custom modules please look here https://www.drupal.org/docs/8/creating-custom-modules

for similar question and answers for drupal 7 look here https://stackoverflow.com/questions/3163537/drupal-automatically-add-menu-items-when-new-nodes-are-added

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.