路由
基本路由
最基本的 Laravel 路由接受一个 URI 和一个闭包,提供了一个简单优雅的方法来定义路由和行为,而不需要复杂的路由配置文件:
use Illuminate\Support\Facades\Route;
Route::get('/greeting', function () {
return 'Hello World';
});
默认路由文件
所有 Laravel 路由都定义在你的路由文件中,它位于 routes
目录。这些文件会被你的应用程序中的 App\Providers\RouteServiceProvider
自动加载。routes/web.php
文件用于定义 web 界面的路由。这些路由被分配给 web
中间件组,它提供了 会话状态和 CSRF 保护等功能。定义在 routes/api.php
中的路由都是无状态的,并且被分配了 api
中间件组。
对于大多数应用程序,都是以在 routes/web.php
文件定义路由开始的。可以通过在浏览器中输入定义的路由 URL 来访问 routes/web.php
中定义的路由。例如,你可以在浏览器中输入 http://example.com/user
来访问以下路由:
use App\Http\Controllers\UserController;
Route::get('/user', [UserController::class, 'index']);
定义在 routes/api.php
文件中的路由是被 RouteServiceProvider
嵌套在一个路由组内。 在这个路由组内,将自动应用 /api
URI 前缀,所以你无需手动将其应用于文件中的每个路由。你可以通过修改 RouteServiceProvider
类来修改前缀和其他路由组选项。
可用的路由方法
路由器允许你注册能响应任何 HTTP 请求的路由
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
有的时候你可能需要注册一个可响应多个 HTTP 请求的路由,这时你可以使用 match
方法,也可以使用 any
方法注册一个实现响应所有 HTTP 请求的路由:
Route::match(['get', 'post'], '/', function () {
// ...
});
Route::any('/', function () {
// ...
});
当定义多个相同路由时,使用 get
, post
, put
, patch
, delete
, 和 options
方法的路由应该在使用 any
, match
, 和 redirect
方法的路由之前定义,这样可以确保请求与正确的路由匹配。
依赖注入
你可以在路由的回调方法中,以形参的方式声明路由所需要的任何依赖项。这些依赖会被 Laravel 的 容器 自动解析并注入。 例如,你可以在闭包中声明 Illuminate\Http\Request
类, 让当前的 HTTP 请求自动注入依赖到你的路由回调中:
use Illuminate\Http\Request;
Route::get('/users', function (Request $request) {
// ...
});
CSRF 保护
请记住,任何指向POST
、PUT
、PATCH
或 DELETE
路由(在 web
路由文件中定义)的 HTML 表单都应该包含 CSRF 令牌字,否则请求会被拒绝。更多 CSRF 保护的相关信息请阅读CSRF 文档:
<form method="POST" action="/profile">
@csrf
...
</form>
重定向路由
如果要定义一个重定向到另一个 URI 的路由,可以使用 Route::redirect
方法。这个方法可以快速的实现重定向,而不再需要去定义完整的路由或者控制器:
Route::redirect('/here', '/there');
默认情况下,Route::redirect
返回 302
状态码。你可以使用可选的第三个参数自定义状态码:
Route::redirect('/here', '/there', 301);
或者,你也可以使用 Route::permanentRedirect
方法返回 301
状态码:
Route::permanentRedirect('/here', '/there');
在重定向路由中使用路由参数时,以下参数由 Laravel 保留,不能使用:destination
和 status
。
视图路由
如果你的路由只需返回一个视图,你可以使用 Route::view
方法。就像 redirect
方法,该方法提供了一个让你不必定义完整路由或控制器的便捷操作。这个view
方法的第一个参数是URI,第二个参数为视图名称。此外,你也可以在可选的第三个参数中传入数组,将数组的数据传递给视图:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
在视图路由中使用参数时,下列参数由 Laravel 保留,不能使用:view
、data
, status
及 headers
。
route:list 命令
使用 route:list
Artisan命令可以轻松提供应用程序定义的所有路线的概述:
php artisan route:list
正常情况下,route:list
不会显示分配给路由的中间件信息;但是你可以通过在命令中添加 -v
选项 来显示路由中的中间件信息:
php artisan route:list -v
你也可以通过 --path
来显示指定的 URL 开头的路由:
php artisan route:list --path=api
此外,在执行 route:list
命令时,可以通过提供 --except vendor
选项来隐藏由第三方包定义的任何路由:
php artisan route:list --except-vendor
同理,也可以通过在执行 route:list
命令时提供 --only vendor
选项来显示由第三方包定义的路由:
php artisan route:list --only-vendor
路由参数
必需参数
有时你将需要捕获路由内的 URI 段。例如,你可能需要从 URL 中捕获用户的 ID。你可以通过定义路由参数来做到这一点:
Route::get('/user/{id}', function (string $id) {
return 'User '.$id;
});
也可以根据你的需要在路由中定义多个参数:
Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});
路由的参数通常都会被放在 {}
,并且参数名只能为字母。下划线 (_
) 也可以用于路由参数名中。路由参数会按路由定义的顺序依次注入到路由回调或者控制器中,而不受回调或者控制器的参数名称的影响。
必填参数
如果你的路由具有依赖关系,而你希望 Laravel 服务容器自动注入到路由的回调中,则应在依赖关系之后列出路由参数:
use Illuminate\Http\Request;
Route::get('/user/{id}', function (Request $request, string $id) {
return 'User '.$id;
});
可选参数
有时,你可能需要指定一个路由参数,但你希望这个参数是可选的。你可以在参数后面加上 ?
标记来实现,但前提是要确保路由的相应变量有默认值:
Route::get('/user/{name?}', function (string $name = null) {
return $name;
});
Route::get('/user/{name?}', function (string $name = 'John') {
return $name;
});
正则表达式约束
你可以使用路由实例上的 where
方法来限制路由参数的格式。 where
方法接受参数的名称和定义如何约束参数的正则表达式:
Route::get('/user/{name}', function (string $name) {
// ...
})->where('name', '[A-Za-z]+');
Route::get('/user/{id}', function (string $id) {
// ...
})->where('id', '[0-9]+');
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
为方便起见,一些常用的正则表达式模式具有帮助方法,可让你快速将模式约束添加到路由:
Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function (string $name) {
// ...
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUuid('id');
Route::get('/user/{id}', function (string $id) {
//
})->whereUlid('id');
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', ['movie', 'song', 'painting']);
如果传入请求与路由模式约束不匹配,将返回 404 HTTP 响应。
全局约束
如果你希望路由参数始终受给定正则表达式的约束,你可以使用 pattern
方法。 你应该在 App\Providers\RouteServiceProvider
类的 boot
方法中定义这些模式:
/**
* 定义路由模型绑定、模式筛选器等。
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}
一旦定义了模式,它就会自动应用到使用该参数名称的所有路由:
Route::get('/user/{id}', function (string $id) {
// 仅当 {id} 是数字时执行。。。
});
编码正斜杠
Laravel 路由组件允许除 /
之外的所有字符出现在路由参数值中。 你必须使用 where
条件正则表达式明确允许 /
成为占位符的一部分:
Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');
注意:仅在最后一个路由段中支持编码的正斜杠。
命名路由
命名路由允许为特定路由方便地生成 URL 或重定向。通过将 name
方法链接到路由定义上,可以指定路由的名称:
Route::get('/user/profile', function () {
// ...
})->name('profile');