vincentchalamon/nav-bundle
vincentchalamon/nav-bundle is a Symfony bundle for building and managing site navigation. It gives you a structured way to define nav items and menus, then render them in your templates, keeping navigation configuration out of controllers and views.
Before writing any code, confirm what you actually have: this is a Symfony bundle, not a Laravel package. The v2.0.0 notes are entirely Symfony-ecosystem (easyadmin-bundle, framework-extra-bundle, symfony/phpunit-bridge, Symfony ^6). Laravel has no bundle system, no DI compiler passes, no config/packages/*.yaml, and Composer's extra.laravel.providers key will be absent — so composer require will install classes that Laravel never auto-wires.
Start in this order:
composer.json → require block. Check the symfony/* constraints. Symfony ^6 is a hard floor, which means Laravel 9/10 only (Laravel 8 pins Symfony ^5 and will fail to resolve). Also check for a type: symfony-bundle and an extra block — anything other than extra.laravel is a red flag.*Bundle.php class. That is the Symfony entry point and the closest analogue to a service provider. Read its build()/load() methods and note every ContainerBuilder call — that list is your to-do list for a Laravel provider.Resources/config/ (or config/). These service definitions (XML/YAML/PHP) tell you which classes are actually public and how they're composed. Ignore anything tagged for kernel.event_subscriber or routing.loader unless you plan to reimplement it.src/ for framework-agnostic classes. Domain services, value objects, and pure-PHP helpers are the only things that transplant cleanly. Everything under DependencyInjection/, Controller/, and Command/ is Symfony-coupled.First real use case: don't try to run the bundle inside Laravel. Pick one of two paths —
Http::baseUrl(config('services.bundle.url')). You keep the bundle's behaviour intact and pay only an integration cost.src/, drop it into app/Services/, and register it in a provider. Do this only for leaf services with no EventDispatcherInterface or RequestStack dependencies.Sidecar integration. Add a config/services.php entry, bind a typed client, and treat the Symfony app as an external dependency:
// config/services.php
'bundle' => [
'url' => env('BUNDLE_URL'),
'token' => env('BUNDLE_TOKEN'),
],
Wrap calls in a small client class with retry() and a circuit-breaker, then dispatch from jobs so a sidecar outage doesn't take down requests. Authenticate with a signed header — the Symfony side won't know about Laravel's session cookies.
Manual container wiring. Translate the bundle's service definitions into a provider. Symfony tags map to Laravel tagged bindings:
kernel.event_subscriber → an EventServiceProvider $listen array or a class calling Event::listen() in boot().console.command → $this->commands([...]) in a provider, after rewriting the command to extend Illuminate\Console\Command.Configuration + TreeBuilder) → a config/bundle.php file plus mergeConfigFrom().Routing and controllers. Symfony attribute routes and the old @Route annotations do not exist in Laravel. If you need the bundle's HTTP surface, proxy it explicitly with Route::any('/bundle/{path?}', ...)->where('path', '.*') rather than trying to reverse-engineer the route definitions. Note that v2.0.0 removed sensio/framework-extra-bundle, so any snippet you find using @Route, @Template, or @ParamConverter reflects v1 docs and will not work against this release.
Views. The bundle ships Twig templates. There is no Twig bridge in Laravel. Either render them in the sidecar and iframe/proxy the HTML, or rewrite to Blade — the latter is rarely worth it for admin UI.
Persistence. If the bundle is Doctrine-backed, do not point Eloquent at its tables and hope. Either give the sidecar sole ownership of its schema and exchange DTOs, or define read-only Eloquent models against a separate connection (config/database.php → bundle connection) with $guarded = ['*'] and no write methods.
easycorp/easyadmin-bundle, sensio/framework-extra-bundle). If you had pinned v1 because it worked with annotated controllers or an EasyAdmin panel, upgrading is a rewrite, not a composer update. Budget accordingly and pin "^1.0" if you can't.illuminate/* packages require symfony/console, symfony/http-foundation, symfony/finder, symfony/process, and symfony/var-dumper. When resolution fails, run composer why-not symfony/http-foundation 6.4.0 and composer depends symfony/http-foundation to find the real culprit instead of guessing. There is no patch that makes this bundle coexist with Laravel 8.phpunit/phpunit → symfony/phpunit-bridge migration is irrelevant to Laravel's own PHPUnit setup, but if you vendor the bundle's test suite you'll inherit bridge listeners that expect a Symfony kernel — skip those tests entirely.extra.laravel.providers only. If classes appear "not found" in the container, it's because nothing registered them. Don't hunt for a missing provider — write one.register(). Grep for CompilerPassInterface and addCompilerPass early; this is the single most common reason an extraction "almost works."ServiceNotFoundException / RuntimeException, which look nothing like Laravel's container errors. Enable a verbose monolog channel on the sidecar and correlate with a request ID passed from Laravel — otherwise cross-process traces are unreadable.EventDispatcher is the most portable seam. If the bundle dispatches events, you can consume them over the sidecar boundary (HTTP webhook or a shared queue) without porting any code, which is far cheaper than reimplementing listeners.How can I help you explore Laravel packages today?