Route(路由)
幂等性:指一次和多次请求某一个资源应该具有同样的副作用,也就是一次访问与多次访问,对这个资源带来的变化是相同的。
路由动作
动词 | 描述 | 是否幂等 |
GET | 获取资源,单个或多个 | 是 |
POST | 创建资源 | 否 |
PUT | 更新资源,客户端提供完整的资源数据 | 是 |
PATCH | 更新资源,客户端提供部分的资源数据 | 否 |
DELETE | 删除资源 | 是 |
注)为什么 PUT 是幂等的而 PATCH 是非幂等的,因为 PUT 是根据客户端提供了完整的资源数据,客户端提交什么就替换为什么,而 PATCH 有可能是根据客户端提供的参数,动态的计算出某个值,例如每次请求后资源的某个参数减1,所以多次调用,资源会有不同的变化。
// 支持的请求方式
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
eg:
资源路由
Route::resource('users', 'UsersController');
等同于
Route::get('/users', 'UsersController@index')->name('users.index');
Route::get('/users/create', 'UsersController@create')->name('users.create');
Route::get('/users/{user}', 'UsersController@show')->name('users.show');
Route::post('/users', 'UsersController@store')->name('users.store');
Route::get('/users/{user}/edit', 'UsersController@edit')->name('users.edit');
Route::patch('/users/{user}', 'UsersController@update')->name('users.update');
Route::delete('/users/{user}', 'UsersController@destroy')->name('users.destroy');
// 闭包路由
Route::get('hello', function () {
return 'Hello, Welcome to LaravelAcademy.org';
});
// 指定路由控制器和方法
Route::get('/user', 'UsersController@index');
// 相应多种http请求
Route::match(['get', 'post'], 'foo', function () {
return 'This is a request from get or post';
});
Route::any('bar', function () {
return 'This is a request from any HTTP verb';
});
// 路由重定向
Route::redirect('/here', '/there', 301); // 在路由定义文件中直接将路由重定向到另一个路由中
// 路由视图, 路由直接指向试图文件
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => '学院君']);
// 资源路由
Route::resource('posts', 'PostController');
(部分资源路由)
Route::resource('post', 'PostController', ['only' =>
['index', 'show']
]);
Route::resource('post', 'PostController', ['except' =>
['create', 'store', 'update', 'destroy']
]);
(API资源路由)
声明被 API 消费的资源路由时,你可能需要排除展示 HTML 模板的路由,如 create 和 edit,为了方便起见,Laravel 提供了 apiResource 方法自动排除这两个路由:
Route::apiResource('post', 'PostController');
(命名资源路由)
默认情况下,所有资源控制器动作都有一个路由名称,不过,我们可以通过传入 names 数组来覆盖这些默认的名称:
Route::resource('post', 'PostController', ['names' =>
['create' => 'post.build']
]);
(命名资源路由参数)
默认情况下,Route::resource 将会基于资源名称的单数格式为资源路由创建路由参数,你可以通过在选项数组中传递 parameters 来覆盖这一默认设置。 parameters 是资源名称和参数名称的关联数组:
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
(补充资源控制器)
如果需要在默认资源路由之外添加额外的路由到资源控制器,应该在调用 Route::resource 之前定义这些路由,否则,通过 resource 方法定义的路由可能无意中覆盖掉补充的额外路由:
Route::get('posts/popular', 'PostController@method');
Route::resource('posts', 'PostController');
// 路由参数
(必选参数)
Route::get('user/{id}', function ($id) {
return 'User ' . $id;
});
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
return $postId . '-' . $commentId;
});
(可选参数)
Route::get('user/{name?}', function ($name = null) {
return $name;
});
Route::get('user/{name?}', function ($name = 'John') {
return $name;
});
(正则约束)
Route::get('user/{name}', function ($name) {
// name 必须是字母且不能为空
})->where('name', '[A-Za-z]+');
Route::get('user/{id}', function ($id) {
// id 必须是数字
})->where('id', '[0-9]+');
Route::get('user/{id}/{name}', function ($id, $name) {
// 同时指定 id 和 name 的数据格式
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
(全局约束)
如果想要路由参数在全局范围内被给定正则表达式约束,可以使用 pattern 方法。需要在 RouteServiceProvider 类的 boot 方法中定义这种约束模式:
/**
* 定义路由模型绑定,模式过滤器等
*
* @param \Illuminate\Routing\Router $router
* @return void
* @translator http://laravelacademy.org
*/
public function boot()
{
Route::pattern('id', '[0-9]+');
parent::boot();
}
// 命名路由
Route::get('user/profile', function () {
// 通过路由名称生成 URL
return 'my url: ' . route('profile');
})->name('profile');
Route::get('user/profile', 'UserController@showProfile')->name('profile');
* 为命名路由生成 URL
$url = route('profile');
$url = route('profile', ['id' => $id]);
* 检查当前路由
如果你想要判断当前请求是否被路由到给定命名路由,可以使用 Route 实例上的 named 方法,例如,你可以从路由中间件中检查当前路由名称:
if ($request->route()->named('profile')) {
//
}
// 路由分组
(中间件)
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second Middleware
});
Route::get('user/profile', function () {
// Uses first & second Middleware
});
});
Route::get('/', function () {
//
})->middleware('token');
Route::get('/', function () {
//
})->middleware('token', 'auth');
(命名空间)
Route::namespace('Admin')->group(function () {
// Controllers Within The "App\Http\Controllers\Admin" Namespace
});
(子域名路由)
Route::domain('{account}.blog.dev')->group(function () {
Route::get('user/{id}', function ($account, $id) {
return 'This is ' . $account . ' page of User ' . $id;
});
});
(路由前缀)
Route::prefix('admin')->group(function () {
Route::get('users', function () {
// Matches The "/admin/users" URL
});
});
// 路由模型绑定
(隐式绑定)
Laravel 会自动解析定义在路由或控制器动作(变量名匹配路由片段)中的 Eloquent 模型类型声明,例如(我们将这个路由定义在 routes/api.php 文件中):
Route::get('users/{user}', function (App\User $user) {
dd($user);
});
* 自定义键名
如果你想要在隐式模型绑定中使用数据表的其它字段而不是 id 字段,可以重写 Eloquent 模型类的 getRouteKeyName 方法,以 User 模型为例,可以在该模型类中添加这个方法 :
/**
* Get the route key for the model.
*
* @return string
*/
public function getRouteKeyName()
{
return 'name';
}
http://blog.dev/api/users/username 访问就可以获取注入的用户模型
(显式绑定)
有隐式绑定,就有显式绑定。要注册显式绑定,可以使用路由器的 model 方法来为给定参数指定绑定类。你需要在 RouteServiceProvider 类的 boot 方法中定义显式模型绑定:
public function boot()
{
parent::boot();
Route::model('user_model', App\User::class);
}
// 路由eg
$router->get('profile/{user_model}', function(App\User $user) {
dd($user);
});
* 自定义解析逻辑
如果你想要使用自定义的解析逻辑,可以在 RouteServiceProvider 类的 boot 方法中使用 Route::bind 方法,传递到 bind 方法的闭包会获取到 URI 请求参数中的值,并且返回你想要在该路由中注入的类实例:
public function boot()
{
parent::boot();
Route::bind('user', function($value) {
return App\User::where('name', $value)->first();
});
}
// 访问当前路由
$route = Route::current(); // 获取当前路由实例
$name = Route::currentRouteName(); // 获取当前路由名称
$action = Route::currentRouteAction(); // 获取当前路由action属性