faizankamal/symfony-route-inspector
A Symfony package for inspecting registered routes from the console. It lists methods, paths, controllers, middleware, and names, helping you audit routing, debug conflicts, and find unused endpoints quickly.
symfony-route-inspector is a small inspection layer over the Symfony/Laravel router. Because Laravel's Route facade is a thin wrapper around Symfony\Component\Routing\Route, the package lets you enumerate and inspect the underlying route definitions (methods, path, controller/handler, defaults, requirements, options) rather than only the formatted Laravel view.
Minimal steps:
Install the package:
composer require faizankamal7/symfony-route-inspector
Laravel should auto-discover the service provider. If not, register it manually in config/app.php.
Publish any config (check for a config/route-inspector.php after install):
php artisan vendor:publish --provider="FaizanKamal7\SymfonyRouteInspector\RouteInspectorServiceProvider"
Look first at the package README and the service provider class — it tells you the exact command name and whether inspection is exposed as an artisan command, a facade, or both. In v1.0.0 the surface area is small, so the provider + one command/class is usually the whole API.
First use case: audit your route table.
php artisan route:inspect
(Verify the exact signature in the README — packages in this space commonly use route:inspect, routes:inspect, or route:list:inspector.) Use it to answer "which controller method actually handles this URI, and what defaults/requirements are attached?" — information route:list flattens away.
Route auditing before a refactor. Run the inspector against your app and export the output, then diff before/after a routing change. This catches silently dropped routes, changed controller actions, and altered parameter requirements that route:list's table view obscures.
CI guardrails. Wrap the inspector in a small artisan command or test to assert conventions:
$routes = app(RouteInspector::class)->all(); // verify accessor name in README
foreach ($routes as $route) {
$this->assertStringStartsWith('admin.', $route->getName() ?? '');
}
This is the highest-value day-to-day pattern: turning route metadata into an enforceable contract rather than a manual review step.
Filtering instead of grepping. Prefer the package's filter options (method, name prefix, URI pattern) over piping route:list through grep. Inspecting by method is especially useful when you have GET/POST pairs on the same URI with different handlers.
Documentation generation. Serialize the inspected collection to JSON and feed it into an API docs generator or an internal wiki. Because you get the Symfony-level Route object, you have access to getDefaults(), getRequirements(), and getOptions() — richer than the Laravel-formatted output.
Debugging 404s and method mismatches. When a route "should" exist but doesn't match, inspect the underlying route's requirements and compiled path. This distinguishes "route not registered" from "route registered but regex requirement rejected the request" — a distinction route:list does not surface clearly.
Complement, don't replace, route:list. Keep php artisan route:list for quick human-readable checks; reach for the inspector when you need programmatic access or the raw Symfony route definition.
php artisan route:cache has been run, the router loads from bootstrap/cache/routes-v7.php and the inspector reflects cached state, not your routes/*.php files. Always php artisan route:clear before trusting inspection output during debugging.getDefault('_controller') returns a Closure for closure-based routes. Guard against this when extracting controller class/method strings, or you'll get type errors or Closure::__toString failures.composer update.Route concept. Middleware lives in Laravel's route action array, not the Symfony route object. If the inspector only surfaces Symfony-level data, you'll need Route::getRoutes() (Laravel) alongside it to resolve middleware — including group-level middleware, which is merged at collection time, not stored per-route.getHost() is separate from getPath(); a naive URI-only filter will miss or misgroup tenant routes. Check host explicitly if you run multi-tenant routing.composer.json ("^1.0" is fine, but avoid dev-main). Wrap direct calls behind your own thin service so a minor-version rename doesn't ripple through your codebase.boot() on the hot path.app()->extend() or rebind it in a service provider to add custom filters (e.g., "only routes with a tenant default") without forking the package. Check the provider's bindings first — that's usually the cleanest customization seam.How can I help you explore Laravel packages today?