9

I've dig into Drupal menu core to find out a way to build an associative array from a menu tree(eg,the account menu) so that I can output the data as json format. But it seems not possible to do this with Drupal 8. The info I need from a menu tree include title, description, url, and I also need to know whether it has sub menu and if it's enabled. All this can be easily achieved using menu_build_tree() function in Drupal 7. Please understand I tried the so-called Drupal 8 equivalent of menu_build_tree() (\Drupal::menuTree();) but it just gives me large object using which I don't know how to extract the data I need.

2 Answers 2

18

You can load up the menu tree with MenuLinkTree::load, which will give you an array of menu links to work with. From there it's just a matter of looping through and getting what you need, e.g.

$tree = \Drupal::menuTree()->load('main', new \Drupal\Core\Menu\MenuTreeParameters());
foreach ($tree as $item) {
  $title = $item->link->getTitle();
  $url_obj = $item->link->getUrlObject();
  $has_children = $item->hasChildren;
  // etc...
}

The link is a MenuLinkInterface, each item itself is a MenuLinkTreeElement.

It would be preferable to inject the menu.link_tree service if possible, rather than getting it from \Drupal.

0
10

I'm quite late, but maybe helps someone looking for answers, here's my solution for generating recursive array from menu items.

private function generateSubMenuTree(&$output, &$input, $parent = FALSE) {
$input = array_values($input);
foreach($input as $key => $item) {
  //If menu element disabled skip this branch
  if ($item->link->isEnabled()) {
    $key = 'submenu-' . $key;
    $name = $item->link->getTitle();
    $url = $item->link->getUrlObject();
    $url_string = $url->toString();

    //If not root element, add as child
    if ($parent === FALSE) {
      $output[$key] = [
        'name' => $name,
        'tid' => $key,
        'url_str' => $url_string
      ];
    } else {
      $parent = 'submenu-' . $parent;
      $output['child'][$key] = [
        'name' => $name,
        'tid' => $key,
        'url_str' => $url_string
      ];
    }

    if ($item->hasChildren) {
      if ($item->depth == 1) {
        $this->generateSubMenuTree($output[$key], $item->subtree, $key);
      } else {
        $this->generateSubMenuTree($output['child'][$key], $item->subtree, $key);
      }
    }
  }
}

And call that function with

//Get drupal menu
$sub_nav = \Drupal::menuTree()->load('sub-navigation', new \Drupal\Core\Menu\MenuTreeParameters());
//Generate array
$this->generateSubMenuTree($menu_tree2, $sub_nav);
1

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.