人称外号大脸猫

Laravel 12 路由系统详解:从基础到高级应用

路由是任何Web应用的骨架,它决定了HTTP请求如何被处理。Laravel12 在延续优雅路由风格的同时,引入了更强大的功能。本文将全面解析Laravel12 的路由使用技巧。

基础路由定义

定义基础GET路由:

// routes/web.php
Route::get('/', function () {
    return view('welcome');
});

// 控制器路由
Route::get('/dashboard', [DashboardController::class, 'index']);

支持多种HTTP方法:

Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);

Route::match(['GET', 'POST'], '/profile', function () {
    // 处理GET和POST请求
});

// 处理所有HTTP方法
Route::any('/contact', function () {
    // 处理任意类型的请求
});

路由参数处理

必选参数与可选参数:

// 必选参数
Route::get('user/{id}', function ($id) {
    return "User ID: " . $id;
});

// 可选参数
Route::get('profile/{name?}', function ($name = 'Guest') {
    return "Welcome, " . $name;
});

正则表达式约束:

Route::get('posts/{id}', function ($id) {
    return "Post ID: ". $id;
})->where('id', '[0-9]+');

// 多参数约束
Route::get('category/{category}/post/{post}', function ($category, $post) {
    // ...
})->where(['category' => '[A-Za-z]+', 'post' => '[0-9]+']);

命名路由与URL生成

定义命名路由:

Route::get('settings', [SettingsController::class, 'show'])
     ->name('settings.show');

生成URL:

<!-- Blade模板中使用 -->
<a href="{{ route('settings.show') }}">设置</a>

<!-- 带参数 -->
<a href="{{ route('profile', ['name' => 'john']) }}">John's Profile</a>

路由分组与中间件

路由分组:

Route::middleware(['auth'])->group(function () {
    Route::get('/account', [AccountController::class, 'index']);
    Route::get('/billing', [BillingController::class, 'show']);
});

前缀与子域名路由:

// 路径前缀
Route::prefix('admin')->group(function () {
    Route::get('users', [AdminUserController::class, 'index']);
});

// 子域名路由
Route::domain('{store}.example.com')->group(function () {
    Route::get('product/{id}', function ($store, $id) {
        // ...
    });
});

路由特性

缓存路由:

php artisan route:cache // 缓存路由文件
php artisan route:cache --compress  // 压缩缓存文件
php artisan route:clear // 清除缓存

动态速率限制

Route::middleware('throttle:rate_limit,1')->group(function () {
    // 从数据库或配置读取rate_limit值
});

枚举路由绑定(新增)

enum StatusEnum: string {
    case Pending = 'pending';
    case Approved = 'approved';
    case Rejected = 'rejected';
}

Route::get('/status/{status}', function (StatusEnum $status) {
    // URL参数自动转换为枚举实例
    return "状态: " . $status->value;
});

资源路由

// 标准资源路由
Route::resource('posts', PostController::class);

// API资源路由(排除create/edit路由)
Route::apiResource('posts', PostController::class);

// 嵌套资源路由
Route::resource('posts.comments', CommentController::class);

// 自定义资源路由
Route::resource('photos', PhotoController::class)->only([
    'index', 'show'
])->names([
    'index' => 'photos.all'
]);

路由模型绑定

// 隐式绑定(自动注入模型)
Route::get('users/{user}', function (User $user) {
    return $user->email;
});

// 自定义绑定逻辑
Route::get('posts/{post:slug}', function (Post $post) {
    return $post;
});

视图路由

// 简单视图返回
Route::view('/welcome', 'welcome');

// 带参数的视图
Route::view('/profile', 'profile', ['name' => 'John']);

// 当在使用Inertia.js vue或者react时,可以使用以下代码
Route::get('/inertia', function () {
    return Inertia::render('inertia');
});

验证路由列表

php artisan route:list
php artisan route:list --path=api // 仅显示api路由
php artisan route:list --method=GET // 仅显示GET方法路由

跨域资源共享

php artisan config:publish cors

// config/cors.php中配置
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000'],
'allowed_headers' => ['*'],

实践

当管理后台需要配置域名时,开发环境可能不需要配置域名,生产环境需要配置域名,可以使用以下代码:

# bootstrap/app.php中

->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        then: function () {
            // 后台管理端  这里不要添加前缀,因为后台管理端是通过域名访问的,不需要前缀
            Route::middleware('web')->name('admin.')->group(base_path('routes/admin.php'));
        },
    )

开发环境还是可以直接通过路由访问后台管理端,生产环境需要配置域名,可以使用以下代码: 开发环境访问: http://127.0.0.1/admin/dashboard 生成环境访问: http://admin.example.com/dashboard

# routes/admin.php中
// 根据环境应用域名包装
if (!app()->environment('local')) {
    Route::domain(env('APP_DOMAIN', '{store}.example.com'))->group($routeHandler);
} else {
    Route::prefix('admin')->group($routeHandler);
}
$routeHandler = function () {
    Route::get('/', function () {
        return view('welcome')->name('welcome');
    });
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard.index');
    Route::get('/settings', [SettingsController::class,'show'])->name('settings.show');
    Route::middleware(['auth'])->group(function () {
        Route::get('/account', [AccountController::class, 'index'])->name('account.index');
        Route::get('/billing', [BillingController::class,'show'])->name('billing.show');
    });
};

当然,为了避免路由找不到出现404这种情况,页面或者接口中应使用name的方式生成url,而不是直接使用url的方式,这样可以避免路由找不到的情况,例如:

// 正确
<a href="{{ route('admin.dashboard.index') }}">Dashboard</a>
// 错误
<a href="/admin/dashboard">Dashboard</a>

这样还有一个好处就是可以动态的更换后台域名,只需要保持路由的name不变即可

总结

Laravel 12的路由系统在保持简洁语法的同时,通过性能优化和枚举绑定等新特性提升了开发体验。关键要点:

  • 使用路由分组组织逻辑
  • 善用命名路由生成URL
  • 结合路由模型绑定减少冗余代码
  • 利用route:list调试路由
  • 使用Laravel 12的新速率限制保护关键路由

通过合理应用这些特性,可以构建出既高效又易于维护的路由结构,为应用奠定坚实的基础。

copyright ©2025 ahimu.com all rights reserved 皖ICP备19021547号-1