Laravel 13 路由高级特性
路由是 Laravel 应用的入口点,Laravel 13 提供了丰富的高级路由特性,帮助开发者构建灵活、强大的 URL 结构。
路由模型绑定
隐式绑定
1 2 3 4 5 6 7 8 9 10
| use App\Models\User; use App\Models\Post;
Route::get('/users/{user}', function (User $user) { return $user; });
Route::get('/posts/{post}', function (Post $post) { return $post; });
|
自定义键名
1 2 3 4 5 6 7
| Route::get('/users/{user:slug}', function (User $user) { return $user; });
Route::get('/posts/{post:slug}', function (Post $post) { return $post; });
|
显式绑定
1 2 3 4 5 6 7 8 9 10
| use App\Models\User; use App\Models\Post;
Route::model('user', User::class); Route::model('post', Post::class);
Route::bind('user', function (string $value) { return User::where('slug', $value)->firstOrFail(); });
|
自定义默认行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| use App\Models\User; use Illuminate\Routing\Route;
Route::bind('user', function (string $value, Route $route) { $withTrashed = $route->parameter('withTrashed', false); $query = User::query(); if ($withTrashed) { $query->withTrashed(); } return $query->where('slug', $value)->firstOrFail(); });
|
软删除模型绑定
1 2 3 4 5
| use App\Models\User;
Route::get('/users/{user}', function (User $user) { return $user; })->withTrashed();
|
路由组
中间件组
1 2 3 4
| Route::middleware(['auth', 'verified'])->group(function () { Route::get('/dashboard', [DashboardController::class, 'index']); Route::get('/profile', [ProfileController::class, 'show']); });
|
命名空间组
1 2 3 4
| Route::prefix('admin')->name('admin.')->group(function () { Route::get('/users', [UserController::class, 'index'])->name('users.index'); Route::get('/posts', [PostController::class, 'index'])->name('posts.index'); });
|
子域名路由
1 2 3 4 5 6 7 8 9
| Route::domain('{account}.example.com')->group(function () { Route::get('/', function (string $account) { return "Account: {$account}"; }); Route::get('/users/{user}', function (string $account, User $user) { return compact('account', 'user'); }); });
|
前缀和名称组
1 2 3 4
| Route::prefix('api/v1')->name('api.v1.')->group(function () { Route::apiResource('users', UserController::class); Route::apiResource('posts', PostController::class); });
|
路由参数约束
正则约束
1 2 3 4 5 6 7 8 9 10 11
| Route::get('/users/{id}', function (string $id) { return User::findOrFail($id); })->where('id', '[0-9]+');
Route::get('/users/{name}', function (string $name) { return User::where('name', $name)->firstOrFail(); })->where('name', '[A-Za-z]+');
Route::get('/posts/{slug}', function (string $slug) { return Post::where('slug', $slug)->firstOrFail(); })->where('slug', '[a-z0-9-]+');
|
全局约束
1 2 3 4 5 6 7 8
| public function boot(): void { Route::pattern('id', '[0-9]+'); Route::pattern('slug', '[a-z0-9-]+'); parent::boot(); }
|
编码约束
1 2 3
| Route::get('/search/{query}', function (string $query) { return Search::query($query)->get(); })->where('query', '.*')->utf8();
|
命名路由
生成 URL
1 2 3 4 5 6 7 8
| Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { return compact('user', 'post'); })->name('users.posts.show');
$url = route('users.posts.show', [$user, $post]); $url = route('users.posts.show', ['user' => $user, 'post' => $post]); $url = route('users.posts.show', [$user->id, $post->slug]);
|
检查当前路由
1 2 3 4 5 6 7
| if (request()->routeIs('users.*')) { }
if (request()->routeIs('users.index', 'users.show')) { }
|
资源路由
标准资源路由
1 2 3 4 5 6 7 8 9 10
| Route::resource('users', UserController::class);
Route::get('/users', [UserController::class, 'index'])->name('users.index'); Route::get('/users/create', [UserController::class, 'create'])->name('users.create'); Route::post('/users', [UserController::class, 'store'])->name('users.store'); Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show'); Route::get('/users/{user}/edit', [UserController::class, 'edit'])->name('users.edit'); Route::put('/users/{user}', [UserController::class, 'update'])->name('users.update'); Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy');
|
API 资源路由
1 2 3 4 5 6 7 8
| Route::apiResource('users', UserController::class);
Route::get('/users', [UserController::class, 'index'])->name('users.index'); Route::post('/users', [UserController::class, 'store'])->name('users.store'); Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show'); Route::put('/users/{user}', [UserController::class, 'update'])->name('users.update'); Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy');
|
部分资源路由
1 2
| Route::resource('users', UserController::class)->only(['index', 'show']); Route::resource('posts', PostController::class)->except(['create', 'edit']);
|
嵌套资源路由
1 2 3 4 5
| Route::resource('users.posts', UserPostController::class);
|
浅层嵌套
1 2 3 4 5
| Route::resource('users.posts', UserPostController::class)->shallow();
|
资源参数名称
1 2
| Route::resource('users', UserController::class)->parameter('users', 'user'); Route::resource('posts', PostController::class)->parameter('posts', 'post:slug');
|
单动作控制器
1 2 3 4 5 6 7 8 9 10 11
| Route::get('/home', HomeController::class); Route::get('/about', AboutController::class);
class HomeController extends Controller { public function __invoke() { return view('home'); } }
|
回退路由
1 2 3 4 5 6 7 8
| Route::fallback(function () { return response()->view('errors.404', [], 404); });
Route::fallback(function () { return redirect()->route('home'); })->where('path', '^(?!api).*$');
|
路由中间件快捷方式
1 2 3 4 5 6 7 8 9 10 11 12 13
| Route::get('/profile', [ProfileController::class, 'show']) ->middleware('auth');
Route::get('/admin', [AdminController::class, 'index']) ->middleware(['auth', 'admin']);
Route::get('/posts/{post}', [PostController::class, 'show']) ->can('view', 'post');
Route::get('/settings', [SettingsController::class, 'index']) ->name('settings') ->middleware('auth') ->withoutMiddleware(VerifyCsrfToken::class);
|
路由签名 URL
临时签名 URL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| use Illuminate\Support\Facades\URL;
$url = URL::temporarySignedRoute( 'unsubscribe', now()->addMinutes(30), ['user' => $user->id] );
Route::get('/unsubscribe/{user}', function (Request $request) { if (! $request->hasValidSignature()) { abort(401); } })->name('unsubscribe');
|
永久签名 URL
1
| $url = URL::signedRoute('verify-email', ['user' => $user->id]);
|
验证签名
1 2 3 4 5 6 7 8 9
| Route::get('/verify-email/{user}', function (Request $request, User $user) { if (! $request->hasValidSignature()) { return redirect()->route('login')->with('error', 'Invalid link'); } $user->markEmailAsVerified(); return redirect()->route('dashboard'); })->name('verify-email')->middleware('signed');
|
路由缓存
缓存路由
清除缓存
缓存注意事项
1 2 3 4 5 6 7
| Route::get('/closure', function () { return 'Hello'; });
Route::get('/controller', [Controller::class, 'method']);
|
路由模型绑定高级用法
自定义异常
1 2 3 4 5 6 7 8 9 10
| use App\Models\User; use Illuminate\Database\Eloquent\ModelNotFoundException;
Route::bind('user', function (string $value) { try { return User::where('slug', $value)->firstOrFail(); } catch (ModelNotFoundException $e) { throw new UserNotFoundException($value); } });
|
预加载关联
1 2 3 4 5 6 7 8 9
| Route::get('/users/{user}', function (User $user) { return $user; })->middleware(function ($request, $next) { $request->route()->setParameter( 'user', User::with('posts', 'comments')->findOrFail($request->route('user')) ); return $next($request); });
|
条件路由
环境条件
1 2 3 4
| Route::when(app()->environment('local'), function () { Route::get('/dev', [DevController::class, 'index']); Route::get('/debug', [DebugController::class, 'index']); });
|
配置条件
1 2 3 4
| Route::when(config('features.blog'), function () { Route::resource('posts', PostController::class); Route::resource('categories', CategoryController::class); });
|
路由重定向
简单重定向
1 2 3
| Route::redirect('/here', '/there'); Route::redirect('/here', '/there', 301); Route::permanentRedirect('/old', '/new');
|
带参数重定向
1
| Route::redirect('/users/{id}', '/profile/{id}');
|
路由视图
简单视图路由
1 2
| Route::view('/welcome', 'welcome'); Route::view('/about', 'about', ['title' => 'About Us']);
|
最佳实践
1. 使用路由组组织路由
1 2 3 4 5 6 7 8 9
| Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () { Route::resource('users', AdminUserController::class); Route::resource('posts', AdminPostController::class); });
Route::get('/admin/users', [AdminUserController::class, 'index'])->middleware('auth')->name('admin.users.index'); Route::get('/admin/users/create', [AdminUserController::class, 'create'])->middleware('auth')->name('admin.users.create');
|
2. 合理使用资源路由
1 2 3 4 5 6 7
| Route::apiResource('posts', PostController::class);
Route::get('/posts', [PostController::class, 'index']); Route::post('/posts', [PostController::class, 'store']); Route::get('/posts/{post}', [PostController::class, 'show']);
|
3. 使用路由模型绑定
1 2 3 4 5 6 7 8 9
| Route::get('/users/{user}', function (User $user) { return $user; });
Route::get('/users/{id}', function ($id) { return User::findOrFail($id); });
|
总结
Laravel 13 的路由系统功能强大且灵活,通过合理使用路由模型绑定、路由组、资源路由和签名 URL 等特性,可以构建出清晰、安全、可维护的 URL 结构。记住使用路由缓存来优化生产环境性能,并遵循 RESTful 设计原则来组织 API 路由。