路由
基本路由
构建基本路由只需要一个 URI 与一个 闭包
,这里提供了一个非常简单优雅定义路由的方法:
Route::get('foo', function () {
return 'Hello World';
});
默认路由文件
所有的 Laravel 路由都在 routes 目录中定义,这些文件都由框架自动加载。routes/web.php 文件用于定义 web 界面的路由。这里面的路由会被分配给 web 中间件组,它提供了会话状态和 CSRF 保护等功能。 定义在 routes/api.php 中的路由都是无状态的,并且被分配了 api 中间件组。
大多数的应用构建,都是以在 routes/web.php 文件定义路由开始的。可以通过在浏览器中输入定义的路由 URL 来访问 routes/web.php 中定义的路由。例如,你可以在浏览器中输入 http://your-app.test/user 来访问以下路由:
use App\Http\Controllers\UserController;
Route::get('/user', [UserController::class, 'index']);
routes/api.php 文件中定义的路由通过 RouteServiceProvider 被嵌套到一个路由组里面。在这个路由组中,会自动添加 URL 前缀 /api 到此文件中的每个路由,这样你就无需再手动添加了。你可以在 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 () {
//
});
依赖注入
CSRF 保护
指向 web 路由文件中定义的 POST, PUT, PATCH, 或 DELETE 路由的任何 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
.
视图路由
如果你的路由只需要返回一个 view,你可以使用 Route::view 方法。 像 redirect 方法一样, 此方法提供了一个简单的快捷方式,因此您不必定义完整的路由或控制器。 该 view 方法接受 URI 作为其第一个参数,并接受视图名称作为其第二个参数。另外,您可以提供一个数据数组作为可选的第三个参数传递给视图:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
注意:当在图路由使用路线参数,下面的参数是由 Laravel 保留,不能使用:
view
,data
,status
, 和headers
.
路由参数
必填参数
有时您将需要捕获路由内的 URI 段。例如,您可能需要从 URL 中捕获用户的 ID。您可以通过定义路由参数来做到这一点:
Route::get('/user/{id}', function ($id) {
return 'User '.$id;
});
也可以根据您的需要在路由中定义多个参数:
Route::get('/posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
路由的参数通常都会被放在 {}
,并且参数名只能为字母。 下划线 (_
) 也可以用于路由参数名中。路由参数会按路由定义的顺序依次注入到路由回调或者控制器中 - ,而不受回调或者控制器的参数名称的影响。
参数和依赖注入
use Illuminate\Http\Request;
Route::get('/user/{id}', function (Request $request, $id) {
return 'User '.$id;
});
可选参数
有时,你可能需要指定一个路由参数,但你希望这个参数是可选的。你可以在参数后面加上 ?
标记来实现,但前提是要确保路由的相应变量有默认值:
Route::get('/user/{name?}', function ($name = null) {
return $name;
});
Route::get('/user/{name?}', function ($name = 'John') {
return $name;
});
正则表达式约束
你可以使用路由实例上的 where
方法约束路由参数的格式。where
方法接受参数名称和定义参数应如何约束的正则表达式:
Route::get('/user/{name}', function ($name) {
//
})->where('name', '[A-Za-z]+');
Route::get('/user/{id}', function ($id) {
//
})->where('id', '[0-9]+');
Route::get('/user/{id}/{name}', function ($id, $name) {
//
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
为了方便起见,一些常用的正则表达式模式具有帮助程序方法,这些方法可以使你快速向路由添加模式约束:
Route::get('/user/{id}/{name}', function ($id, $name) {
//
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function ($name) {
//
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function ($id) {
//
})->whereUuid('id');
中间件
要给路由组中所有的路由分配中间件,可以在 group 之前调用 middleware
方法,中间件会依照它们在数组中列出的顺序来运行:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// 使用 first 和 second 中间件
});
Route::get('user/profile', function () {
// 使用 first 和 second 中间件
});
});
子域名路由
路由组也可以用来处理子域名。子域名可以像路由 URI 一样被分配路由参数,允许你获取一部分子域名作为参数给路由或控制器使用。可以在定义 group
之前调用 domain
方法来指定子域名:
Route::domain('{account}.myapp.com')->group(function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
注意:为了确保您的子域名路由是可访问的,您应该在注册根域名路由之前注册子域名路由。这将防止根域名路由覆盖具有相同 URI 路径的子域名路由。
..
路由命名
路由命名可以方便地为指定路由生成 URL 或者重定向。通过在路由定义上链式调用 name
方法可以指定路由名称:
Route::get('/user/profile', function () {
//
})->name('profile');
你还可以指定控制器行为的路由名称:
Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
注意:路由命名必须是唯一的
生成指定路由的 URL
一旦为路由指定了名称,你可以在生成 url 或者通过 Laravel 的 route
和 redirect
辅助函数重定向时使用路由的名字:
// 生成链接...
$url = route('profile');
// 生成重定向...
return redirect()->route('profile');
如果有定义参数的命名路由,可以把参数作为 route
函数的第二个参数传入,指定的参数将会自动插入到 URL 中对应的位置:
Route::get('/user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1]);
如果在数组中传递其他参数,这些键或值对将自动添加到生成的 URL 查询字符串中:
Route::get('/user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
技巧:有时候,你可能希望为某些 URL 参数的请求范围指定默认值,例如在本地环境,你可以使用
URL::defaults
方法.
路由前缀
prefix
方法将会为路由组中的每一个 URI 添加前缀。例如,您可以给该组中所有的 URI 添加 admin
的前缀:
Route::prefix('admin')->group(function () {
Route::get('users', function () {
// Matches The "/admin/users" URL
});
});
路由名称前缀
name 方法可以为路由组中每一个路由名称添加一个指定的字符串作为前缀。例如,您可以给已经分组的路径添加 admin 的前缀。给定的字符串与指定的路由名称前缀完全相同,因此我们将确保在前缀中提供尾部的 . 字符:
Route::name('admin.')->group(function () {
Route::get('users', function () {
// Route assigned name "admin.users"...
})->name('users');
});