Menu entity), then resolve the most specific match at render time.
A common use case is a multi-tenant SaaS where each partner — or even each operator within a partner — has a customised sidebar menu, with a generic fallback for everyone else.
How context resolution works
EachMenu entity has an optional context field (stored as a JSON object, e.g. {"partnerId": 1, "operatorId": 1}). When you pass a list of context objects (“context sets”), the bundle tries them in order and returns the first menu whose code and context both match.
- Most specific first — put the tightest match at the start of the list.
- Fallback last — use
{}(ornull) at the end to match menus with no context. - If nothing matches, the tree is empty.
Rendering in Twig
Pass thecontextSets array as the third argument to dashboard_menu_tree and as the second argument to dashboard_menu_config:
Using the JSON API
When calling the API endpoint, pass the same list as the_context_sets query parameter, JSON-encoded:
{} last.
Real-world scenario: per-partner menus
Suppose you have three menus in the database, all with codesidebar:
| Menu code | Context | Description |
|---|---|---|
sidebar | {"partnerId": 1, "operatorId": 7} | Custom menu for operator 7 under partner 1 |
sidebar | {"partnerId": 1} | Default menu for all of partner 1 |
sidebar | {} (none) | Global fallback for all other users |
Programmatic code resolution with MenuCodeResolverInterface
For more complex scenarios — such as deriving the menu code itself from request attributes — implement MenuCodeResolverInterface. The resolved code is then looked up with context sets as usual.
MenuCodeResolverInterface in config/services.yaml:
config/services.yaml
The same resolver is called for both Twig (
dashboard_menu_tree('sidebar')) and the API (GET /api/menu/sidebar). The hint is the string you pass to the function or the {code} segment in the URL.Ordering rules summary
- Pass context sets in most-specific → least-specific order.
- Always end the list with
{}if you want a global fallback. - Passing
nullor an empty array is equivalent to looking up a menu with no context. - The resolved menu determines which tree and which config are returned.