Skip to content

Grouping Routes by Prefix

When you have multiple routes that start with the same path segments—like /api/v1/... or /admin/...—use a group instead of repeating the prefix on every route.

app()->group('/api', function($app) {
$app->get('/users', fn() => User::all());
$app->get('/posts', fn() => Post::all());
});

Both routes register with the /api prefix, so you get /api/users and /api/posts.

The real power of groups is applying middleware to multiple routes at once. Instead of adding authentication to each admin route individually, add it to the group:

app()->group('/admin', function($app) {
$app->get('/dashboard', fn() => 'admin dashboard');
$app->get('/users', fn() => User::all());
})->use(AuthMiddleware::class);

Now both /admin/dashboard and /admin/users require authentication.

You can nest groups to build up complex URL structures. This is useful for API versioning or organizing features by module:

app()->group('/api', function($app) {
$app->group('/v1', function($app) {
$app->get('/users', fn() => 'v1 users');
});
$app->group('/v2', function($app) {
$app->get('/users', fn() => 'v2 users');
});
});

This registers /api/v1/users and /api/v2/users without repeating /api for each version.

When a group needs several middleware—like CORS, rate limiting, and authentication—chain multiple use() calls:

app()->group('/api', function($app) {
$app->get('/users', fn() => User::all());
})->use(CorsMiddleware::class)
->use(RateLimitMiddleware::class)
->use(AuthMiddleware::class);

Middleware executes in the order you add it—CORS first, then rate limiting, then authentication.

Groups are great for shared prefixes and middleware, but if you need more isolation—like separate error handlers or different middleware stacks—check out the guide on creating sub-applications. Sub-apps give you completely independent request processing with their own configuration.