Laravel 路由使用进阶
常言道「物以类聚,人以群分」,同样,在日常开发中,我们通常会将具有某些共同特征的路由进行分组,这些特征包括是否需要认证、是否具有共同的路由前缀或者子域名、以及是否具有相同的控制器命名空间等,显然,对路由按照共同特征进行分组后可以避免重复为某些路由定义相同的路由特征,让代码更加简洁,可读性和可维护性更好。
所谓路由分组,其实就是通过 Route::group
将几个路由聚合到一起,然后给它们应用对应的共享特征:
Route::group([], function () {
Route::get('hello', function () { return 'Hello'; });
Route::get('world', function () { return 'World'; });
});
由于没有应用任何共享特征(第一个参数是空数组),所以这样的路由分组其实并没有什么意义,下面我们来介绍一些常见的共享特征设置。
1、中间件
我们使用路由分组最常见的场景恐怕就是为一组路由应用共同的中间件了,关于中间件可以参考官方文档(https://xueyuanjun.com/post/9539.html),后面也会有单独章节来讲解,使用中间件可以对 HTTP 请求进行过滤或重定向,比如以认证中间件(别名auth
)为例,如果用户已经认证可以进行后续处理,否则将会把用户重定向到登录页面。
下面我们就来创建一个包含 dashboard
和 account
的路由分组,这两个路由都需要认证,所以我们可以通过 Route::middleware
为其设置共同的中间件 auth
并以此对其进行分组:
Route::middleware('auth')->group(function () {
Route::get('dashboard', function () {
return view('dashboard');
});
Route::get('account', function () {
return view('account');
});
});
如果是多个中间件,可以通过数组方式传递参数,比如 ['auth', 'another']
,以上是 Laravel 5.5+ 提供的新语法,在此之前的版本,需要这么调用:
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function () {
return view('dashboard');
});
Route::get('account', function () {
return view('account');
});
});
当然,链式调用只是语法糖,底层最终还是下面 Route::group
这种定义实现的,感兴趣的同学可以去看下源码是如何实现的:vendor/laravel/framework/src/Illuminate/Routing/RouteRegistrar.php
,下面路径前缀、子域名和命名空间的链式调用原理也是一样,以后我们都用链式调用来定义,因为这样代码可读性更好。
2、路由路径前缀
如果某些路由拥有共同的路径前缀,例如,所有 API 路由都以 /api
前缀开头,我们可以使用 Route::prefix
为这个分组路由指定路径前缀并对其进行分组:
Route::prefix('api')->group(function () {
Route::get('/', function () {
// 处理 /api 路由
})->name('api.index');
Route::get('users', function () {
// 处理 /api/users 路由
})->name('api.users');
});
3、子域名路由
子域名路由和路由路径前缀一样,不过是通过子域名而非路径前缀对分组路由进行约束,子域名路由有两个使用场景,一个是为应用子系统设置不同的子域名:
Route::domain('admin.blog.test')->group(function () {
Route::get('/', function () {
// 处理 http://admin.blog.test 路由
});
});
另一个是通过参数方式设置子域名,适用于网站拥有多租户的场景(比如天猫,顶级知名商家拥有自己独立的子域名,如 https://xiaomi.tmall.com
):
Route::domain('{account}.blog.test')->group(function () {
Route::get('/', function ($account) {
//
});
Route::get('user/{id}', function ($account, $id) {
//
});
});
这种情况下,$account
永远是所有分组路由的第一个路由参数。
4、子命名空间
以控制器方式定义路由的时候,当我们没有显式指定控制器的命名空间时,默认的命名空间是 AppHttpControllers
(在 app/Providers/RouteServiceProvider.php
中设置),如果某些控制器位于这个命名空间下的子命名空间中,该如何设置分组规则呢?我们可以通过 Route::namespace
为同一子命名空间下的分组路由设置共同的子命名空间:
Route::get('/', 'Controller@index');
Route::namespace('Admin')->group(function() {
// AppHttpControllersAdminAdminController
Route::get('/admin', 'AdminController@index');
});
5、路由命名前缀
除了通过上述共同特征对路由进行分组外,对于某一类资源路由,比如用户,往往拥有相同的路由命名前缀,如 user.
,我们还可以基于这一特征对路由进行分组,使用 Route::name
方法即可实现:
// 路由命名+路径前缀
Route::name('user.')->prefix('user')->group(function () {
Route::get('{id?}', function ($id = 1) {
// 处理 /user/{id} 路由,路由命名为 user.show
return route('user.show');
})->name('show');
Route::get('posts', function () {
// 处理 /user/posts 路由,路由命名为 user.posts
})->name('posts');
});
在这个示例中,我们通过链式调用的方式为该路由分组应用了路由命名前缀和路由路径前缀两个共享特征,我们还可以组合调用上述所有五个特征,调用方法参考上面这种链式调用,从而组合出更加复杂的分组规则。
(全文完)
- Oracle Data Guard延迟的原因(r11笔记第69天)
- 一个细小的空间问题触发的报警(r11笔记第68天)
- MySQL误操作数据恢复的简单实践(r11笔记第67天)
- Oracle 12c中JOB运行失败的简单处理(r11笔记第66天)
- MySQL中的半同步复制(r11笔记第65天)
- Linux系统LVM逻辑卷创建过程以及自动化脚本
- 一个闪回区报警的数据恢复(r11笔记第62天)
- 利用腾讯云COS云对象存储定时远程备份网站
- 分享一个自写的Python远程命令和文件(夹)传输类
- Oracle数据误操作全面恢复实战(r11笔记第78天)
- 远程协助解决异常宕库的问题(r11笔记第75天)
- Nginx-helper纯代码版,文章评论发布自动清理Fastcgi缓存
- MySQL和Oracle行值表达式对比(r11笔记第74天)
- 闪回数据库不是“万金油”(r11笔记第73天)
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC