everlutionsk/navigation-bundle
A Symfony bundle for rendering multiple navigation instances that are registered dynamically via tagged services. It supports containers, nested items, routing, breadcrumbs, filtering, sorting, translation, and highlighting the current item.
Read this first: everlutionsk/navigation-bundle is a Symfony Bundle, not a Laravel package. There is no service provider, no config/navigation.php, and no way to composer require it into a Laravel app and have it "just work." As a Laravel developer, your realistic options are:
everlutionsk/navigation library (which is framework-agnostic) and write your own Laravel integration layer — a service provider that binds containers, plus a Blade directive/component in place of the Twig renderer.If you are working in a Symfony codebase, the setup is minimal:
composer require everlutionsk/navigation-bundleEverlution\NavigationBundle\EverlutionNavigationBundle::class => ['all' => true] to config/bundles.php; Symfony 3 → add it to AppKernel::registerBundles().Where to look first: the README's Usage section, then the bundle's DependencyInjection/ directory and any CompilerPass. The exact tag names and tag attributes (container name, priority, etc.) live there — do not trust blog snippets or AI answers for the string literals; confirm them against the source before copying.
First use case to validate the package with: a header/main menu built entirely from tagged services. Create one item class, tag it, register it into a named container, render that container in your base template, and confirm the item appears. If that loop works, everything else (active states, filters, multiple containers) is incremental.
Item-as-a-service. The core idea is that each navigation item is a DI-managed service, not an array entry in a config file. That's the package's whole value proposition: item visibility, labels, and route parameters can depend on injected services (current user, feature flags, tenant context) with proper constructor injection and testability. Use one class per logical item, or a small set of parameterized item classes if you have repetitive links.
Named containers + multi-registration. Items are grouped into containers, and a single item can be registered into more than one container. This is what you want for "the Dashboard link appears in the sidebar, the mobile drawer, and the breadcrumb root." Register once, attach to multiple containers, and let each container's render template control presentation.
Rendering. Rendering is delegated to the bundle's renderer service / Twig function, given a container name and a template. Keep one template per navigation shape (navbar, sidebar, breadcrumb, footer) rather than one mega-template with conditionals — the item contract is intentionally thin, so presentation belongs in Twig.
Active/current-item highlighting. Do this in the item, not the template. Inject RequestStack (or the router plus current route) and compare route name and parameters. The package supports route-with-parameters on items specifically so that /orders/{id} and /orders/{id}/edit can be distinguished — naive "starts with" matching will highlight both.
Route parameters and dynamic parameters. Static params are declared on the item. Dynamic params (tenant slug, current user id, locale) are resolved at render time — that's why the item needs access to request/context services. Keep dynamic resolution lazy; don't compute in the constructor if it depends on the request.
Filtering. Filters let you strip items at render time (by role, feature flag, environment). Prefer filters over if blocks in Twig — it keeps policy in PHP where it's unit-testable, and it means the same container can be rendered differently per context without duplicating templates.
Suggested workflow.
src/Navigation/Item/ — item classes, autoconfigured/tagged.src/Navigation/Container/ — one class or config entry per container (main, footer, admin).src/Navigation/Filter/ — role/flag filters.templates/navigation/*.html.twig — one template per shape.base.html.twig so every page inherits it.Third-party extension pattern. The tagged-service model means another bundle can contribute items without touching your central navigation config. If you're building a modular app, this is the pattern to lean on — but document your tag names, because silent typos produce silently empty menus.
bin/console debug:container --tag=<your.tag> (confirm the tag string in the bundle source first). A typo yields an empty array, not an exception.cache:clear (or a fresh cache warmup in dev).RequestStack must not be resolved during container compilation or in a long-running worker context without care. In Symfony's request scope it's fine; in Messenger/CLI contexts the request is absent — guard for null.debug:container --tag=… → debug:router (confirm route names/params exactly) → dump() the container contents before rendering → check the Twig template actually receives the expected variable.composer.json, and be prepared to vendor/fork if it stalls — the code surface is small, so forking is realistic.How can I help you explore Laravel packages today?