各位小伙伴,再本套课程中5-24节singwa老师预留了一个作业,需要大家自行的去完成资源路由的解读,现将答案公布如下:
我们已路由设置场景如下:
Route::resource('res', 'index/res'); Route::rule('abcd/:name', 'index/hello');
我们都知道在RuleGroup类中的check方法中$rules变量其实有几种对象,第一种就是RuleItem对象:
think\route\RuleItem,另外一种是 : think\route\Resource对象 , $rules变量中的内容再路由设置分析课程内容做了详细的介绍,这里就不过多的讲解了,我们定位到RuleGroup类中的check方法中的foreach 如下代码:
// 检查分组路由 foreach ($rules as $key => $item) { $result = $item->check($request, $url, $completeMatch); // 标注1 if (false !== $result) { return $result; } }
如上代码 标注1中 针对我们的路由配置会有两种场景的走向,第一种就是会请求RuleItem类中的check方法 这个在视频中做了非常详细的讲解,那么第二种就是会请求Resource对象中的check, Resource这个类中并没有check方法,但是他继承了RuleGroup类,这个类中存在check方法,很巧的就是这个方法就是上面标黑的check方法。
图一
然后很多小伙伴就很诡异怎么请求半天又回来了,哈哈,别着急,再编码过程中这种现成很正常,继续看代码如下:
图二
这个时候 我们的当前对象就是 资源Resource对象了, 而上图二中 instanceof关键词是类型运算符 用于确定一个 PHP 变量是否属于某一类 class 的实例 , 他会走到下面这个逻辑,然后请求buildResourceRule方法,这个方法实际是在ResourceRule类中,如下:
/** * 生成资源路由规则 * @access protected * @return void */ protected function buildResourceRule() { $origin = $this->router->getGroup(); // think\route\Domain $this->router->setGroup($this); $rule = $this->resource; $option = $this->option; if (strpos($rule, '.')) { // 注册嵌套资源路由 $array = explode('.', $rule); $last = array_pop($array); $item = []; foreach ($array as $val) { $item[] = $val . '/<' . (isset($option['var'][$val]) ? $option['var'][$val] : $val . '_id') . '>'; } $rule = implode('/', $item) . '/' . $last; } $prefix = substr($rule, strlen($this->name) + 1); // 注册资源路由 foreach ($this->rest as $key => $val) { if ((isset($option['only']) && !in_array($key, $option['only'])) || (isset($option['except']) && in_array($key, $option['except']))) { continue; } if (isset($last) && strpos($val[1], '<id>') && isset($option['var'][$last])) { $val[1] = str_replace('<id>', '<' . $option['var'][$last] . '>', $val[1]); } elseif (strpos($val[1], '<id>') && isset($option['var'][$rule])) { $val[1] = str_replace('<id>', '<' . $option['var'][$rule] . '>', $val[1]); } $this->addRule(trim($prefix . $val[1], '/'), $this->route . '/' . $val[2], $val[0]); } $this->router->setGroup($origin); }
这个方法主要是对资源路由的多个场景内容做了些处理,下面图三中的内容很关键:
图三
这个地方遍历 让7种资源路由重新 注册到规则中 ($this->addRule()) ,然后请求RuleGroup中的addRule方法,如图四:
图四
这个方法我们在之前路由注册的时候做了详细的分析的,这里老师就不过讲解了, 那么通过这些操作后,我们在回到图一中的check方法,这个时候他的$rules变量就彻底变了 大家可以打印出来看看效果如下:
array(4) { [0] => object(think\route\RuleItem)#22 (10) { ["hasSetRule"] => bool(true) ["name"] => string(15) "index/res/index" ["rule"] => string(3) "res" ["method"] => string(3) "get" ["vars"] => array(0) { } ["option"] => array(1) { ["complete_match"] => bool(true) } ["pattern"] => array(0) { } ["mergeOptions"] => array(6) { [0] => string(5) "after" [1] => string(5) "model" [2] => string(6) "header" [3] => string(8) "response" [4] => string(6) "append" [5] => string(10) "middleware" } ["doAfter"] => NULL ["lockOption"] => bool(false) } [1] => object(think\route\RuleItem)#16 (10) { ["hasSetRule"] => bool(true) ["name"] => string(16) "index/res/create" ["rule"] => string(10) "res/create" ["method"] => string(3) "get" ["vars"] => array(0) { } ["option"] => array(0) { } ["pattern"] => array(0) { } ["mergeOptions"] => array(6) { [0] => string(5) "after" [1] => string(5) "model" [2] => string(6) "header" [3] => string(8) "response" [4] => string(6) "append" [5] => string(10) "middleware" } ["doAfter"] => NULL ["lockOption"] => bool(false) } [2] => object(think\route\RuleItem)#24 (10) { ["hasSetRule"] => bool(true) ["name"] => string(14) "index/res/edit" ["rule"] => string(13) "res/<id>/edit" ["method"] => string(3) "get" ["vars"] => array(0) { } ["option"] => array(0) { } ["pattern"] => array(0) { } ["mergeOptions"] => array(6) { [0] => string(5) "after" [1] => string(5) "model" [2] => string(6) "header" [3] => string(8) "response" [4] => string(6) "append" [5] => string(10) "middleware" } ["doAfter"] => NULL ["lockOption"] => bool(false) } [3] => object(think\route\RuleItem)#23 (10) { ["hasSetRule"] => bool(true) ["name"] => string(14) "index/res/read" ["rule"] => string(8) "res/<id>" ["method"] => string(3) "get" ["vars"] => array(0) { } ["option"] => array(0) { } ["pattern"] => array(0) { } ["mergeOptions"] => array(6) { [0] => string(5) "after" [1] => string(5) "model" [2] => string(6) "header" [3] => string(8) "response" [4] => string(6) "append" [5] => string(10) "middleware" } ["doAfter"] => NULL ["lockOption"] => bool(false) } }
细心的同学会发现 这个时候数组里面的内容全是
think\route\RuleItem
对象了, 那么这里为什么是 4个 而不是7个呢? 留给大家思考下。然后继续走
图五
通过forach循环 然后调用check方法,那么这个时候就最终走到RuleItem类中的check方法,哈哈又回到了原点,这个RuleItem类中的check方法之前视频中做了详细的分析。 完美了。哈哈。
热门评论