Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Route Discovery Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/laravel-route-discovery
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Spatie\RouteDiscovery\RouteDiscoveryServiceProvider"
    
  2. Basic Setup: Add this to your routes/web.php (or routes/api.php):

    use Spatie\RouteDiscovery\Facades\Discover;
    
    Discover::controllers()->in(app_path('Http/Controllers'));
    
  3. First Use Case: Annotate a controller method with [Route]:

    use Spatie\RouteDiscovery\Attributes\Route;
    
    class UserController extends Controller
    {
        #[Route('/users', name: 'users.index')]
        public function index()
        {
            return view('users.index');
        }
    }
    

    Now, visiting /users will trigger the index method.


Where to Look First

  • Documentation: Spatie's Route Discovery Docs
  • Attributes: Focus on #[Route], #[Middleware], #[View], and #[Resource].
  • Config: config/route-discovery.php (if published) for customization.

Implementation Patterns

Usage Patterns

  1. Controller-Based Routing: Replace Route::get(), Route::post(), etc., with attribute-based routing in controllers:

    #[Route('/dashboard', name: 'dashboard')]
    public function showDashboard()
    {
        return view('dashboard');
    }
    
  2. Middleware Assignment: Apply middleware to specific routes or controllers:

    #[Middleware(['auth', 'verified'])]
    class ProfileController extends Controller
    {
        #[Route('/profile', name: 'profile')]
        public function show()
        {
            // ...
        }
    }
    
  3. View-Based Routing: Use #[View] to auto-generate routes for Blade views:

    Discover::views()->in(resource_path('views'));
    

    Then annotate Blade files:

    @route('/about', name: 'about')
    
  4. Resource Routes: Define RESTful resource routes with #[Resource]:

    #[Resource]
    class PostController extends Controller
    {
        // All CRUD methods auto-discovered
    }
    
  5. Dynamic Segments: Use parameters in route paths:

    #[Route('/posts/{post}', name: 'posts.show')]
    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }
    

Workflows

  1. Incremental Adoption: Start by migrating one controller at a time. Use Discover::controllers()->in() to include specific directories.

  2. API + Web Separation: Use separate Discover calls for web and api routes:

    // routes/web.php
    Discover::controllers()->in(app_path('Http/Controllers/Web'));
    
    // routes/api.php
    Discover::controllers()->in(app_path('Http/Controllers/API'));
    
  3. Testing: Test routes by asserting their existence in routes/web.php or via Route::has():

    $this->assertTrue(Route::has('users.index'));
    
  4. Cache Warmup: Run php artisan route:clear and php artisan route:cache after changes to reflect updates.


Integration Tips

  1. Custom Attributes: Extend the package by creating custom attributes:

    #[Attribute]
    class RateLimited implements RouteAttribute
    {
        public function __construct(public string $limit) {}
    
        public function handle(RouteDefinition $route): void
        {
            $route->middleware('throttle:' . $this->limit);
        }
    }
    
  2. Route Model Binding: Leverage Laravel's built-in binding (e.g., Post $post) in annotated methods.

  3. API Versioning: Use middleware or subdirectories to version API routes:

    Discover::controllers()
        ->in(app_path('Http/Controllers/Api/V1'))
        ->prefix('api/v1');
    
  4. Fallback Routes: Combine attribute-based routes with traditional Route::fallback() for catch-all logic.


Gotchas and Tips

Pitfalls

  1. Route Caching:

    • Changes to annotated routes won’t reflect until you run php artisan route:clear and route:cache.
    • Tip: Use php artisan route:list to verify routes after changes.
  2. Namespace Conflicts:

    • Ensure controller classes are in directories included via Discover::controllers()->in().
    • Fix: Explicitly specify the namespace or adjust autoloading.
  3. Middleware Order:

    • Middleware applied via #[Middleware] runs after global middleware but before route-specific middleware in web.php.
    • Tip: Use ->before() or ->after() on Discover to control order:
      Discover::controllers()->in(...)->before('auth');
      
  4. View Discovery Quirks:

    • Discover::views()->in() only works with Blade files. Static HTML files are ignored.
    • Tip: Use #[Route] for non-Blade routes.
  5. Attribute Overrides:

    • Route attributes override traditional Route::get() definitions. Avoid mixing both in the same app.

Debugging

  1. Route Not Found:

    • Check if the controller is in a discovered directory.
    • Verify the attribute syntax (e.g., #[Route] vs @Route).
    • Run php artisan route:list to debug.
  2. Middleware Not Applied:

    • Ensure middleware names are correct (e.g., 'auth' vs 'auth:sanctum').
    • Check for typos in #[Middleware] or Discover config.
  3. Cache Issues:

    • Clear config cache (php artisan config:clear) if routes persist after changes.

Config Quirks

  1. Excluded Directories:

    • Use ->exclude() to ignore specific directories:
      Discover::controllers()->in(app_path('Http/Controllers'))->exclude('Tests');
      
  2. Route Naming:

    • Default route names are derived from method names (e.g., indexusers.index).
    • Tip: Always specify name in #[Route] for clarity.
  3. Attribute Precedence:

    • Class-level attributes (e.g., #[Middleware] on the controller) apply to all methods.
    • Method-level attributes override class-level ones.

Extension Points

  1. Custom RouteAttribute: Implement Spatie\RouteDiscovery\Attributes\RouteAttribute to create reusable logic:

    #[Attribute]
    class ApiDoc implements RouteAttribute
    {
        public function handle(RouteDefinition $route): void
        {
            $route->addTags(['api']);
        }
    }
    
  2. Event Listeners: Listen to RouteDiscovered events to log or modify routes dynamically:

    use Spatie\RouteDiscovery\Events\RouteDiscovered;
    
    RouteDiscovered::listen(function (RouteDiscovered $event) {
        logger()->info('Discovered route:', ['uri' => $event->route->uri]);
    });
    
  3. Service Provider: Override the registerRoutes method in your service provider to customize discovery:

    public function registerRoutes()
    {
        Discover::controllers()
            ->in(app_path('Http/Controllers'))
            ->prefix('app')
            ->middleware('web');
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport