<?php
use App\Models\Post;
use App\Models\Comment;
use Illuminate\Support\Facades\Route;
// Implicit binding - auto-resolves Post by ID
Route::get('/posts/{post}', function (Post $post) {
return view('posts.show', compact('post'));
});
// Bind by slug instead of ID
Route::get('/posts/{post:slug}', function (Post $post) {
return view('posts.show', compact('post'));
});
// Scoped binding - ensures comment belongs to post
Route::get('/posts/{post}/comments/{comment}', function (Post $post, Comment $comment) {
return view('comments.show', compact('post', 'comment'));
})->scopeBindings();
// Include soft-deleted models
Route::get('/posts/{post}', function (Post $post) {
return view('posts.show', compact('post'));
})->withTrashed();
// Custom missing behavior
Route::get('/posts/{post}', function (Post $post) {
return view('posts.show', compact('post'));
})->missing(function () {
return response()->view('errors.404', [], 404);
});
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// Custom route key
public function getRouteKeyName(): string
{
return 'slug';
}
// Customize resolution
public function resolveRouteBinding($value, $field = null)
{
// Custom logic for resolving model
return $this->where($field ?? $this->getRouteKeyName(), $value)
->published()
->firstOrFail();
}
public function scopePublished($query)
{
return $query->whereNotNull('published_at');
}
}
<?php
namespace App\Providers;
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Explicit binding
Route::bind('post', function ($value) {
return Post::where('slug', $value)
->published()
->firstOrFail();
});
// Bind with custom model
Route::model('admin', User::class);
// Bind with callback
Route::bind('user', function ($value) {
return User::where('username', $value)->firstOrFail();
});
}
}
Route model binding automatically resolves Eloquent models from route parameters, eliminating manual lookups. Implicit binding matches parameter names to model IDs—/users/{user} injects the User model. Custom route keys use getRouteKeyName() to bind by slug instead of ID. Explicit binding in RouteServiceProvider provides full control over resolution logic. Soft-deleted models are excluded unless using withTrashed(). Scoped bindings enforce parent-child relationships—/posts/{post}/comments/{comment} ensures the comment belongs to the post. Missing models return 404 automatically. This feature reduces boilerplate and improves security by centralizing authorization checks.