I'm trying to get a specific menu link to a node but we have a giant menu structure with more than one link to the same node.

$menu_links = $menu_link_service->loadLinksByRoute('entity.node.canonical', $route_params, $menu_name);

This code works but $menu_links sometimes has multiple links.  The Menu UI module somehow keeps track of only a single menu link even if there are multiple links in the same menu to that node. I'm calling this the menu ui link, though maybe there's a better way to refer to it.

I'm wondering how I can get this menu ui link from a node. I see some people use:

$menu_link = reset($menu_links);

Is the first element guaranteed to the be the same as the menu ui link or are people operating on the assumption that they only have one link and just using reset to access the first element of the array?

Is there another way to get the menu ui link?

thanks in advance!

Comments

jlessinger’s picture

I dug into Menu UI and found this code:

$query = \Drupal::entityQuery('menu_link_content')
          ->condition('link.uri', 'entity:node/' . $node_id)
          ->condition('menu_name', 'main')
          ->sort('id', 'ASC')
          ->range(0, 1);
        
$result = $query->execute();

if (!empty($result)) {
   $menu_link = \Drupal\menu_link_content\Entity\MenuLinkContent::load(reset($result));
   ...
}

This query sort by ID ascending and on return the first result so the first link added is the one Menu UI uses.

while this code:

$menu_links = $menu_link_service->loadLinksByRoute('entity.node.canonical', $route_params, $menu_name);

I believe this sorts by the array keys which are menu link plugin ids and not guaranteed to in any particular order.