用trait模拟中间件
备注:本文针对tp5.0,由于tp不同版本的兼容性问题很多,以下这些内容仅供参考
tp5请求层,在路由调用控制器之前,没有中间件拦截。那么,你是什么时间检查用户的token或session?只能在控制器的init中调用。当然,也可以使用hook。但发现,hook太傻了。在实现上有诸多不便,基本上不能满足这一需求。
最后,只能选择trait.这时,发现tp5用trait的地方极少。这个模拟多重继承,通过mixin增强单一责职的如此优秀的功能,居然很少被用到,难怪一个类好几十个方法。
实现的方法是,定义两个trait,一个叫WithAuth,另一个叫WithoutAuth。在前一个中实现从request中获取token,检查登录,获取用户数据。后一个,直接同名函数中返回空值就行了。这样做好后,需要登录的控制器,用WithAuth,基它用WithoutAuth即可。
同样,对于API项目,一样可以用这一方法来实现接口签名。
但这样做是比在每个函数中加一行强多了。但是,相对于在路由中分组,使用不同的中间件,只能是差强人意。
但是有些中间件就没有这么幸运了,比如,request,它不是由App类来管理加载的。而是用的单例。我就奇怪了,App这个超全局的顶层对象居然不是单例的,你无法通过App进行管理与操作。这已充分说明,tp的开发者根本不懂设计模式,可能这话有些过份,但是,有多少好的PHP框架,App不是单例的,又有多少编程语言没有App单例?我不知tp用户为何说它好。这就像一个天生牙痛的人,他的想法一定是,牙不可能不痛,而牙不痛才是生病。这种错误已经低级得无法说了。
记忆中的微软公司的VB98,那可真是1998年发行的。在那个时候,一个应用都有一个全局的APP对象了。但是,可惜,这个号称10年磨一剑的tp5.0,它虽然有个APP类,但绝对不是单例的,且连构造函数都没有。这个App类对应用有管理作用吗?无!!!!并且,它本质上只是一个程序启动的执行。一个框架有这样的错,不只是低级错误问题,而是功能不完整了!
正因为request到处use,那换不掉。这时我不由得又想起了,Laravel框架中,对于这些框架内部的组件类,全部采用Faced模式,把类配置在App的config中的。把控制权交给你,你想换哪一个都行。同时,Laravel的Request类是基于全世界最优秀的symfony,的Http-Kenel开发的。我不清楚tp开发者是如何想的,优秀组件不用,你是全能神吗?
我要对request数据后处理。把驼峰的改成下划线的,怎么办呢?继承现有request,增加方法进行转换,然后替换params属性。这其中发现,request的代码让人无比抓狂。它读取GET,POST,REQUEAT全是混在一起的,一锅粥,你无法通过继承单一改写某个读取。并且,它的这些读取是随调随读的,所以即使重写这些混乱的代码也不能做到,怎么办呢,只能用params方法全部读取,然后再把params属性中的替换掉。这样,算是成功了。但成功之后,心里仍慌,因为,弄不准还会有什么问题,同时tp中没有单元测试配置的,你无法方便地进行单元测试。因为要测,还要安装thinkTest,想像不出来,一个框架,在现今,连单元测试都没有集成,还有人敢用,不得不服tp的市场能力。再想到tp的测试覆盖率29%(而这好像是最新版的6.0),只求上帝保佑了。