TPEZ 我和PHP的梦幻情缘
编辑前言
“PHP是世界上最好的语言”
这句话最早出现在2001年7月的PHP文档中,21世纪初,PHP一直是Web开发中的统治力量。[1]然而,时过境迁,在2021年的当下,PHP已经黯然失色。[2]目前招聘中主流的后端岗位都以Java、Golang、C++为主,PHP岗位大不如前。这句话也变成了讽刺PHP开发者的梗。
然而,PHP却是陪伴我大学三年成长之路的可谓最亲密的伙伴,它见证我做出第一个Web项目,帮助我完成一个个课程设计、参赛项目、外包项目,跟着我南征北战。从大一开始学习PHP,到大一下学期使用ThinkPHP5.0完成Quanta杯的项目,到大二上学期用ThinkPHP5.0重构思政学时3.0,再到大三上用ThinkPHP6.0重构培训学时,对TP属实是感情深厚。
(更多我的ThinkPHP文章可见https://blog.csdn.net/weixin_43409309/category_10168077.html)
在使用ThinkPHP框架做开发的过程中,发现每次在新建项目的时候,我都会去找以前项目的代码,重用里面的封装。久而久之,就萌生了做一个再封装框架的想法。虽然封装的内容不多,但都是我认为优雅的实现。后续若在开发中遇到新的想法,可能还会更新。若有谬误之处,欢迎大佬指正。
简介
项目地址(欢迎star):https://github.com/LeslieLeung/TPEZ
TPEZ(读作tp easy)是一个基于ThinkPHP6.0.x再封装的框架,旨在帮助新手更快上手ThinkPHP框架,同时方便老手快速基于本框架进行项目开发。TPEZ凝聚作者三年PHP项目开发经验,对一些项目共性的功能(如JSON返回、权限管理、controller-service-model结构等)进行封装,方便后端同学使用TPEZ作为脚手架进行后续开发。同时,提供了登录、用户端、管理端模拟等示例接口,供前端同学学习。
特性
-
对控制器返回Json进行了封装
-
实现了权限管理机制(使用中间件)
-
实现了token封装
-
扩充了基本框架(增加service层,将业务逻辑与模型和控制器分开)
-
增加了若干范例(包括controller、service、route、env等的使用)
-
提供了可用的示例接口供前端学习
-
与官方ThinkPHP6.0.x完全兼容,若后续官方版本更新,可以方便升级
封装思路
基控制器
控制器的基本功能是接受输入,通过业务逻辑层和模型层,返回数据。在项目中比较常用的数据交换格式一般是json,因此首先也是对返回json这一功能进行封装。这一部分主要需要把json封装成固定的格式,如
{
"code": "xxxxx",
"msg": "xxxxx",
"data": {
"key1": "value1",
... // other infos
}
}
因此,用一个ResponseController类继承BaseController类(表示该类为控制器),在里面定义返回json的各种方法(包括json结构、成功、成功(带数据)和失败的方法)(具体见app/controller/ResponseController.php
);新的控制器只需要继承ResponseController,在返回的时候调用如$this→renderSuccess()
即可快速返回json数据。
权限管理
这部分是官方文档一直在暗示但没有实现出来的功能[3]。这部分是我认为最得意的部分,我使用了中间件与路由配合token进行实现,采用了类似Java中拦截器的思路,完全不影响正常业务逻辑(即在业务逻辑中无需考虑权限的问题)。
正常而言,一个请求在tp内部是这样处理的(有部分省略):
请求-->控制器-->逻辑层-->模型层-->逻辑层-->控制器-->回应
若要实现权限的管理,可以通过将权限值和用户信息放在一个数组中,在发放token时,使用token作为key,上述数组作为value存放在缓存中(可以使用file或者redis)。若不使用中间件,可以在逻辑层对token对应的权限值进行校验。然而,这会造成一个很大的问题:耦合度剧增。一个校验权限的逻辑像肿瘤一样侵入到控制器、逻辑层,这显然是不利于维护的。(考虑以下例子:若要修改一个管理权限接口为用户和管理皆可用,需要下到逻辑层进行修改。)
聪明的做法肯定是把权限管理提出来,作为一个最前置的逻辑,对token进行校验。这里就要引入tp中间件了。
中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理。[4]
一个聪明的想法油然而生:在请求时,先根据请求的路径(路由)分配对应的校验中间件,在中间件中校验token、解出请求参数放入上下文(笑死,在学安卓开发,就想到这个表述了)中,然后继续控制器往下的操作。
引入中间件后,处理流程如下:
// token权限正确
请求-->参数检查中间件-->权限检查中间件-->
控制器-->逻辑层-->模型层-->逻辑层-->控制器-->回应
// token权限错误
请求-->参数检查中间件-->权限检查中间件-->返回错误回应
实现上,只需要在中间件中实现权限的检查和请求参数的提取即可。然后,只需要把对应请求的路径注册到路由,然后指定使用权限校验中间件即可。实际上,我实现了一个Auth中间件基类,在新增权限时,只需要继承Auth基类,在enum中新增权限值,然后修改里面的权限值即可。具体的实现见app/middleware/Auth.php
、route/route.php
。
回到刚才修改接口权限的例子,在引入中间件后,只需要在route/route.php
中修改对应接口的中间件即可。如:
// 用户接口
Route::group('user', function() {
// 这里添加用户的接口
// add user apis here
Route::rule('helloUser', 'User/helloUser', 'POST');
Route::rule('helloAdmin', 'Admin/helloAdmin', 'POST'); // 新增用户可访问管理接口
})->middleware([\app\middleware\CheckParam::class, \app\middleware\UserAuth::class]);
Token
Token的封装主要是生成随机key,用用户信息数组作为value将登录态保存到cache中。为了配合上面权限管理增加了role字段。提供了如发token、销毁token(安全退出)、取token等功能。详见app\model\Token.php
。
Best Practice
其他的部分,主要是使用tp框架这几年积累下来比较优雅的一些写法。带强烈个人风格。
controller-service-model
一开始写的时候,所有的业务逻辑都写在model中。后来学Springboot,了解到持久层和业务逻辑层实际上是应该分开的。因此在写PHP中,我也使用了这种分开的方式。在controller中调用service中的业务逻辑,然后service中对持久层进行调用。
另外有一处地方也值得一提,先贴代码。
private $indexService;
private $data;
private $id;
public function __construct(App $app, Request $request)
{
parent::__construct($app);
$this->id = $request->id;
$this->data = $request->data;
$this->indexService = invoke('app\service\IndexService');
}
在控制器中,我先声明了诸如$data, $id
等成员变量,在构造函数中注入。这个trick可以在后续代码中不必再考虑传入的参数,直接访问这几个成员变量就可以获取到。$indexService
的做法则是对Springboot中@Autowired
的模仿。
其他
tp6引入了一个我非常喜欢的功能——环境变量设置(见.env
)。我习惯把诸如servername, ip, token_expire_time
等等随时需要根据部署环境修改的环境变量写在这里,而不用通过hardcode等方式。这个功能在tp5中需要修改一个config.php,实现属实不如tp6优雅。
最后
写完才想起副标题是我与PHP的梦幻情缘,文章却写成了TPEZ的发布会。但我没有跑题,TPEZ就是我跟PHP三年写就的故事。还记得去年的时候,老EO安排我整理PHP后端方向的学习资料,我一直一直没有完成这个任务。前段时间我提议以后塔里新生后端方向与时俱进,从Java入门,不再学PHP了。另外另外,我也打算转Java/Go了,很有可能TPEZ就是我最后一个PHP的项目了,虽然封装很简单,但我觉得是这几年写的PHP项目凝聚出来的,希望对大家有帮助。
最后啰嗦一下,欢迎star我的项目(https://github.com/LeslieLeung/TPEZ),欢迎关注我的微信公众号和博客(https://blog.ameow.xyz/)
引用
[1] 「PHP 是最好的语言」这个梗是怎么来的? - 蓬岸 Dr.Quest的回答 - 知乎
https://www.zhihu.com/question/26498147/answer/315847232 2021.4.22
[2] TIOBE Index for April 2021 https://www.tiobe.com/tiobe-index/ 2021.4.22
[3] 路由·ThinkPHP6.0完全开发手册 https://www.kancloud.cn/manual/thinkphp6_0/1037494 2021.4.22
[4] 中间件·ThinkPHP6.0完全开发手册 https://www.kancloud.cn/manual/thinkphp6_0/1037493 2021.4.22
- 0
- 0
-
赞助
微信赞赏码 -
分享