Route Parameters
Capture segments of the URL and pass them to your handler.
Syntax
Route::get('/users/{id}', $callback);Wrap a URL segment in {braces} to capture it. The captured value is injected into your callback in order. Add a ? to make a parameter optional and give it a default.
Example
use Illuminate\Support\Facades\Route;
Route::get('/users/{id}', function ($id) {
return 'Showing user ' . $id;
});
Route::get('/posts/{slug?}', function ($slug = 'latest') {
return 'Post: ' . $slug;
});When to use it
- A blog displays individual posts by slug, using {post:slug} route model binding so Laravel automatically queries the Post model by the slug column.
- A scoped-binding route like /users/{user}/posts/{post} ensures the displayed post actually belongs to the user in the URL, preventing unauthorised access.
- An optional route parameter allows /search and /search/laravel to share the same controller method, with the keyword defaulting to null when omitted.
More examples
Capture a URL segment
Shows both manual ID capture and implicit route model binding, where Laravel resolves the {post} segment to a Post model via its primary key.
// routes/web.php
Route::get('/posts/{id}', function (int $id) {
return Post::findOrFail($id);
});
// Controller with implicit route-model binding
Route::get('/posts/{post}', [PostController::class, 'show']);
// Laravel injects the Post model automaticallyCustom binding column with {model:column}
Using {post:slug} tells Laravel to query the posts table by the slug column, returning a 404 automatically if no match is found.
// Bind by slug instead of id
Route::get('/posts/{post:slug}', [PostController::class, 'show']);
// In the controller
public function show(Post $post): View
{
return view('posts.show', compact('post'));
// 404 automatically if slug not found
}Optional parameter with a default
The trailing ? makes the segment optional; the parameter defaults to null when the URL contains no keyword, allowing /search and /search/laravel to reuse the same handler.
Route::get('/search/{keyword?}', function (?string $keyword = null) {
$query = Post::query();
if ($keyword) {
$query->where('title', 'like', "%{$keyword}%");
}
return $query->paginate(15);
});
Discussion