spatie/laravel-route-discovery
Automatically discover Laravel routes by scanning controllers and views instead of manually defining them. Configure discovery in your routes files and use PHP attributes to customize names, middleware, and more for each discovered route.
Pros:
routes/web.php or routes/api.php.Route::get(), Route::resource()) without replacing it, enabling hybrid approaches.Discover::controllers()->in(app_path('Modules/Api'))).#[Route(name: 'api.v1.users.index')]).Cons:
Illuminate\Routing).Route::fallback()) still require manual definition.routes/*.php files must be refactored incrementally (attribute migration path exists).spatie/laravel-honeypot).| Risk Area | Severity | Mitigation Strategy |
|---|---|---|
| Attribute parsing | Low | Test with PHP 8.0+; fallback to manual routes if needed. |
| Middleware conflicts | Medium | Audit existing middleware stacks pre-migration. |
| Caching interactions | Low | Clear route cache (php artisan route:clear) post-migration. |
| IDE support | Low | Attributes may not auto-complete in older IDEs (e.g., PHPStorm < 2021.3). |
| Testing impact | Low | Route tests may need updates for attribute-based names/middleware. |
routes/web.php) coexist with discovered routes?Route::get() + #[Route])?@RateLimited) be needed, requiring extension?php artisan route:list --time.)illuminate/routing).RouteServiceProvider (e.g., spatie/laravel-permission route guards).Phase 1: Pilot (Low-Risk)
// Before: routes/web.php
Route::get('/admin/dashboard', [DashboardController::class, 'index']);
// After: DashboardController.php
class DashboardController {
#[Route('/admin/dashboard', name: 'admin.dashboard')]
public function index() { ... }
}
php artisan route:list.Phase 2: Incremental Adoption
Route::resource() with attribute-based discovery where needed:
// Before: routes/api.php
Route::resource('users', UserController::class)->middleware('auth:sanctum');
// After: UserController.php
class UserController {
#[Route('/users', name: 'users.index', middleware: ['auth:sanctum'])]
public function index() { ... }
}
#[Route] attributes.Phase 3: Full Migration
Route::get()/Route::post() calls with attributes.routes/web.php to routes/legacy.php).#[Route(middleware: ['auth', 'throttle:60'])]).php artisan route:cache.#[Route('/users/{user}')]).Illuminate\Http\Resources.Route::get() registration order.RouteServiceProvider.Pre-Migration:
grep -r "Route::" routes/).routes/*.php files.During Migration:
config(['route-discovery.enabled' => env('DISCOVERY_ENABLED', false)]).php artisan route:clear after each batch of changes.Post-Migration:
phpstan rules).routes/*.php files.Route::get()).routes/*.php files to memorize).use Spatie\RouteDiscovery\Attributes\Route; import.#[Route(middleware: ['auth:invalid'])]).php artisan route:clear).php artisan route:list --name="*" to filter discovered routes.php artisan route:clear to reset state.Route::resource() to attributes."How can I help you explore Laravel packages today?