一.问题
碰到个问题,http://local.wx.cntv.cn/auditset/admin/apply/test.html访问不到
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9UkaNRTUq5kMBpnTyU0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2QTMyMzNxUTM5ETOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二.心情
心情无比不好,我检查了各种配置,写了对比的mp路径的...等等吧.都不好使,我最终决定看下源码.
三.流程
(1).我是先看了一遍yii的文档.
a.yii的文档相当于需求,源码是对需求的实现.这样能好理解些.
b.自己的需求是否可以被满足
c.文档中多数会有一些实现逻辑.看源码时能轻松些
(2).熟悉yii实现的大体逻辑,根据报错简单确定下需要看的类(当然这个我是熟悉的)
a.报错类
是web\Application.php这个类报错.找找上下左右大概就能知道需要看什么了.
a.1 第一个类web\Application,先看类参考手册确定下,实现的什么功能,继承关系,有问题的方法都干了什么?
就是这个方法,接收一个request对象(请求信息),返回一个response对象(响应信息),中间就是请求的处理,其中有一步应该是路由解析.
a.2 look look这个方法的实现
(1)是为了处理请求诞生route(路由信息)和param参数,同时包括一个catchAll路由的实现
(2)是通过路由信息诞生action对象,处理参数
a.3 var_dump($route,$param)看看是什么东西?确定下报错的位置
说明根据request已经解析出来route和param了
那报错就是runAction中的问题了.在通过这个路由诞生action对象时有的问题.
a.4
解析一个路由信息,创建对应的module,controller,action实例,之后调用base\Controller的runAction运行action实例传给过来的param参数.
a5
应该是(1)报错了.is_array($parts)不是个数组,报错.
关注一下这个$id,我发现报错没有这个$id/$route 而是$route,那这个$id是个什么呢?
a6 $id是从getUniqueId来的,这个$this是web/Application实际使用的是base/Application的getUniqueId,必然返回''
a7 $route是auditset/admin/apply/index
a8 解析的逻辑是
先分成auditset admin apply index进入一个递归确认的过程
auditset控制器不存在
那么auditset需要是modules中的一个
admin是不是一个控制器,不是.
那么admin需要是auditset模块的子模块的一个.这明显是不成立的.那么就还有别的匹配规则.
因为http://local.wx.cntv.cn/auditset/mp/test/test?mpid=18 解析出来的是auditset/mp/test/test是合法的.有正则规则
a9 具体怎么实现的呢?
1是路由为空走默认路由
2.是//在路径中应该不合法无法解析,trim动作是为了递归时去掉头部的/,下面route进入递归的时候是没有头部的/的.
1.是否是最后一个id,通过是否还有/判断
是: $id = $route 这个id就是控制器映射的id
不是:那么分解路由,第一个/第二个.第一个是$id后面是路由
2.判断$id是否在controller映射中.在就返回了.希望中$controller确认了.后面是action;
1.$this->controllerMap在application为module时,我这个项目是空的.
2.那么去看是不是一个module auditset,是的话去但是controller.
在查看getModule时注意使用的方法实际是什么.$this是web/Application上面是类的继承关系.
1.$id是auditset,load是true.这时var_dump($id)在方法的第一行会出debug说明之前是有这个方法的调用的.
调整一下测试观察的代码
1.加一个debug的标识,我要观察的auditset打断.
2.$this->_modules里面是什么?是配置给application的modules映射列表.
这个setInstance很有意思
其实是维护了一个全局的状态,通过Yii::$app这个类.光看这个调用$module->setInstance($module)是把自己注册到自己身上.有点儿怪怪的.
总之诞生了module对象了.是注册的那个
回到上面,开始创建一个controller,会转回去,解析admin/apply/index,
admin 是找不到module的,那么就是controller的id了.controllerid要么是最后一个字段了没有/
要么是admin/X 和 X+1...到结尾的action,比如 admin/apply/index 就是admin/apply 和index
在寻找controller class的时候class_exists返回的是false,最后对比命名空间发现少写了一个字母,我的类定义里面!
好吧,路由解析就到这儿了.