继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

关于《由浅入深分析Tp5&Tp6底层源码》5-24节作业详解

2019-05-21 00:24:256841浏览

singwa

2实战 · 14手记 · 77推荐
TA的实战

    各位小伙伴,再本套课程中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方法。https://img4.mukewang.com/5ce2cf23000171a513520386.jpg

图一

然后很多小伙伴就很诡异怎么请求半天又回来了,哈哈,别着急,再编码过程中这种现成很正常,继续看代码如下:

https://img.mukewang.com/5ce2cf8000010c2b13620366.jpg

图二

这个时候 我们的当前对象就是 资源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);
}

这个方法主要是对资源路由的多个场景内容做了些处理,下面图三中的内容很关键:

https://img2.mukewang.com/5ce2d27a00017eba21500588.jpg

图三

这个地方遍历 让7种资源路由重新 注册到规则中 ($this->addRule()) ,然后请求RuleGroup中的addRule方法,如图四:

https://img2.mukewang.com/5ce2d3060001c69a18580706.jpg

图四


这个方法我们在之前路由注册的时候做了详细的分析的,这里老师就不过讲解了, 那么通过这些操作后,我们在回到图一中的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个呢? 留给大家思考下。然后继续走https://img4.mukewang.com/5ce2d449000169f214160112.jpg

图五


通过forach循环 然后调用check方法,那么这个时候就最终走到RuleItem类中的check方法,哈哈又回到了原点,这个RuleItem类中的check方法之前视频中做了详细的分析。 完美了。哈哈。

打开App,阅读手记
7人推荐
发表评论
随时随地看视频慕课网APP

热门评论

$this->middleware->add( function (Request $request, $next) use ($dispatch, $data) {
    return is_null($data) ? $dispatch->run() : $data;
});

请问 这里参数$next, 用途是什么?
这里执行的时候犯迷糊了....

查看全部评论