How can I load a menu programmatically with an active trail set by a provided URL? Working on a headless Drupal site, and have come across an issue. We have a REST resource that returns arbitrary menus by menu-id, however they always have "active-trail" set to false on every menu item.

I'd like to be able to specify a URL or route when building the menu and have the active-trail be equivalent to what it would be if the menu was loaded on that route.

At the moment our solution is to loop through every menu item until we find one that corresponds to the provided URL, and then mark it and all its parents as "active-trail", however this seems unnecessarily cumbersome and I'm left wondering if there's a more sensible solution we've overlooked.

Currently we're loading menus like this:

$tree = $this-&gt;menuTree-&gt;load('menu_id', new MenuTreeParameters());


Where $this->menuTree is an instance of MenuLinkTree being instantiated via Dependency Injection:

/**
 * {@inheritdoc}
 */
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, MenuLinkTreeInterface $menu_tree, EntityTypeManagerInterface $entity_type_manager, Request $current_request) {
  parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

  $this-&gt;menuTree = $menu_tree;
  $this-&gt;entityTypeManager = $entity_type_manager;
  $this-&gt;request = $current_request;
  $this-&gt;alias = $this-&gt;request-&gt;query-&gt;get('alias');
}

/**
 * {@inheritdoc}
 */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container-&gt;getParameter('serializer.formats'),
    $container-&gt;get('logger.factory')-&gt;get('rest'),
    $container-&gt;get('menu.link_tree'),
    $container-&gt;get('entity_type.manager'),
    $container-&gt;get('request_stack')-&gt;getCurrentRequest()
  );
}
Inject the menu.active_trail dependency along with menu.link_tree:

private $activeTrail;

/**
 * {@inheritdoc}
 */
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $active_trail, EntityTypeManagerInterface $entity_type_manager, Request $current_request) {
  parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

  $this-&gt;menuTree = $menu_tree;
  $this-&gt;activeTrail = $active_trail;
  $this-&gt;entityTypeManager = $entity_type_manager;
  $this-&gt;request = $current_request;
  $this-&gt;alias = $this-&gt;request-&gt;query-&gt;get('alias');
}

/**
 * {@inheritdoc}
 */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container-&gt;getParameter('serializer.formats'),
    $container-&gt;get('logger.factory')-&gt;get('rest'),
    $container-&gt;get('menu.link_tree'),
    $container-&gt;get('menu.active_trail'),
    $container-&gt;get('entity_type.manager'),
    $container-&gt;get('request_stack')-&gt;getCurrentRequest()
  );
}


Now instead of:

$tree = $this-&gt;menuTree-&gt;load('menu_id', new MenuTreeParameters());


get the active trail ID's just before building your menu and pass it in as part of the parameters:

// Change this to menu machine name.
$menu_id = 'menu_id';

// This should return an array. 
// Array contains menu link uuid's, keyed by the uuid's iirc. 
// For example something like:
//   'menu_link:abcdefg_123' =&gt; 'menu_link:abcdefg_123'
$activeTrailIds = $this-&gt;activeTrail-&gt;getActiveTrailIds($menu_id); 

$params = new MenuTreeParameters();
$params-&gt;setActiveTrail($activeTrailIds);
$tree = $this-&gt;menuTree-&gt;load($menu_id, $params);


This should return you a menu tree with correct active trails.