Laravel 路由
路由基本用法
最基本的Laravel路由接受一个URI和一个Closure,提供了一种非常简单且富有表现力的方法来定义路由:
Route::get('foo', function () {
return 'Hello World';
});
默认路由文件
所有Laravel路由都在路由文件中定义,这些文件位于routes目录中。 这些文件由框架自动加载。 route/web.php
文件定义了用于Web界面的路由。 这些路由被分配了Web中间件组,该组提供了会话状态和CSRF保护等功能。 route/api.php
中的路由是无状态的,并分配了api中间件组。
对于大多数应用程序,首先在routes/web.php
文件中定义路由。 可以通过在浏览器中输入定义的路由的URL来访问route/web.php
中定义的路由。 例如,可以通过在浏览器中导航栏中输入http://your-app.test/user
来访问以下路由:
Route::get('/user', 'UserController@index');
route / 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 () {
//
});
CSRF 保护
在Web路由文件中定义的指向POST,PUT,PATCH或DELETE路由的任何HTML表单都应包含CSRF token字段。 否则,该请求将被拒绝。 我们可以在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');
视图路由
如果我们的 Route
仅需要返回视图,则可以使用Route::view
方法。 与重定向方法一样,此方法提供了一个简单快捷的方式,因此我们不必定义完整的路由或控制器。 view方法接受URI作为其第一个参数,并接受视图名称作为其第二个参数。 另外,可以提供一个数据数组作为可选的第三个参数传递给视图:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
路由参数
必须的参数
有时,需要捕获路由内的URI段。 例如,我们可能需要从URL中捕获用户的ID。 可以通过定义路由参数来做到这一点:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
可以根据自己的需求定义任意数量的参数:
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
路由的参数始终用{}大括号括起来,并且应由字母字符组成,并且不能包含-
字符。 可以使用下划线(_)代替 -
。 路由参数根据其顺序注入到路由回调函数或者控制器中——回调函数或者控制器参数的名称无关紧要。
可选参数
有时,我们可能需要指定一个路由参数,但是该路由参数是可选的,也就是说我们在客户端请求的时候可以不传该参数。 我们可以通过放置一个问号?
在参数名称后进行标记。 确保为路由的相应变量赋予默认值:
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参数,则可以使用pattern方法。 应该在RouteServiceProvider
的boot
方法中定义以下模式:
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
Route::pattern('id', '[0-9]+');
parent::boot();
}
定义模式后,将使用该参数名称将其自动应用于所有路由:
Route::get('user/{id}', function ($id) {
// Only executed if {id} is numeric...
});
编码斜杠 /
Laravel路由组件允许除/之外的所有字符。 必须使用where条件中的正则表达式明确允许/
成为占位符的一部分:
Route::get('search/{search}', function ($search) {
return $search;
})->where('search', '.*');
警告
:仅在最后一个路由段内支持编码的斜杠。
命名路由
通过命名路由,可以方便地生成URL或特定路由的重定向。 可以通过将name方法链接到路由定义上来为路由指定名称:
Route::get('user/profile', function () {
//
})->name('profile');
还可以为控制器操作指定路由名称:
Route::get('user/profile', 'UserProfileController@show')->name('profile');
路由的名称必须是唯一的
由名称获取路由的URL
为给定的路由分配名称后,可以在生成URL或通过全局路由功能重定向时使用该路由的名称:
// 生成 URLs...
$url = route('profile');
// 重定向...
return redirect()->route('profile');
如果命名的路由定义了参数,则可以将参数作为第二个参数传递给route
函数。 给定的参数将自动在正确的位置插入URL:
Route::get('user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1]);
如果在数组中传递其他参数,则这些键/值对将自动添加到生成的URL的 query 中,作为请求的参数:
Route::get('user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
有时,我们可能希望为URL参数指定请求范围的默认值,例如当前语言环境。 为此,可以使用
URL::defaults
方法。
检查当前路由
如果想确定当前请求是否被路由到指定名称的路由,则可以在Route实例上使用named
方法。 例如,我们可以从路由中间件检查当前路由名称:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->route()->named('profile')) {
//
}
return $next($request);
}