tp5.1 路由执行解析 (六)

tp5.1 路由执行解析 (六)_第1张图片

 

1、为什么可以直接使用 Route::get 调用呢?  因为这个是执行的 facade门面模式,就不具体说了,接下来看具体代码的流程

Route::get('hello/:name', 'index/hello');

2、定位到 get  方法,第一个参数是路由规则,第二个是路由地址等等,发现最后都是定位到了 rule 方法,

    /**
     * 注册GET路由
     * @access public
     * @param  string    $rule 路由规则
     * @param  mixed     $route 路由地址
     * @param  array     $option 路由参数
     * @param  array     $pattern 变量规则
     * @return RuleItem
     */
    public function get($rule, $route = '', array $option = [], array $pattern = [])
    {
        return $this->rule($rule, $route, 'GET', $option, $pattern);
    }

3、rule 方法中的 $this->group 是如何获取的?

    /**
     * 注册路由规则
     * @access public
     * @param  string    $rule       路由规则
     * @param  mixed     $route      路由地址
     * @param  string    $method     请求类型
     * @param  array     $option     路由参数
     * @param  array     $pattern    变量规则
     * @return RuleItem
     */
    public function rule($rule, $route, $method = '*', array $option = [], array $pattern = [])
    {
        return $this->group->addRule($rule, $route, $method, $option, $pattern);
    }

   我们会发现在 __construct 中有 setDefaultDomain() 方法,里面有一段 new domain 类,而 Domain 继承了 RuleGroup 类,这样就实例化了 RuleGroup 类,那么定位到  RuleGroup 中的 addRule 方法,如下图

tp5.1 路由执行解析 (六)_第2张图片   

/**
 * 初始化默认域名
 * @access protected
 * @return void
 */
    protected function setDefaultDomain()
    {
        // 默认域名
        $this->domain = $this->host;

        // 注册默认域名
        $domain = new Domain($this, $this->host);

        $this->domains[$this->host] = $domain;

        // 默认分组
        $this->group = $domain;
    }

4、分析 addRule 方法 

      1、 首页自动完整匹配,当  $rule == /  或者为空时  $rule = $

      2、创建路由规则实例,最后进行成员属性定义,走到   setRule 方法中。

  tp5.1 路由执行解析 (六)_第3张图片 

     3、 看到最后 rule 是否为 $,如果是的话,那么 去除 $, 并对 option['complete_match'] 赋值为 true

if ('$' == substr($rule, -1, 1)) {
    // 是否完整匹配
    $rule = substr($rule, 0, -1);

    $this->option['complete_match'] = true;
}

  4、去除左边的 / 符号

  $rule = '/' != $rule ? ltrim($rule, '/') : '';

 5、对 rule 中 有 : 号的 进行 转化。

if (false !== strpos($rule, ':')) {
       $this->rule = preg_replace(['/\[\:(\w+)\]/', '/\:(\w+)/'], ['<\1?>', '<\1>'], $rule);
   s} else {
       $this->rule = $rule;
 }

    比如:rule 为  hello/:name 那么会转化为 hello/

    比如:  rule 为  hello/[:name] 那么会转化为 hello/

6、生成路由标识的快捷访问

    1、分析路由规则中的变量,执行 parseVar 方法,当 rule 中存在 ?号,会 name => 2,否则为 1,

    /**
     * 分析路由规则中的变量
     * @access protected
     * @param  string    $rule 路由规则
     * @return array
     */
    protected function parseVar($rule)
    {
        // 提取路由规则中的变量
        $var = [];

        if (preg_match_all('/<\w+\??>/', $rule, $matches)) {
            foreach ($matches[0] as $name) {
                $optional = false;

                if (strpos($name, '?')) {
                    $name     = substr($name, 1, -2);
                    $optional = true;
                } else {
                    $name = substr($name, 1, -1);
                }

                $var[$name] = $optional ? 2 : 1;
            }
        }
        
        return $var;
    }
array(1) {
  ["name"] => int(2)
}
array(1) {
  ["name"] => int(1)
}

   2、生成 变量 $value    

 $value = [$this->rule, $vars, $this->parent->getDomain(), $suffix, $this->method];

 

array(5) {
  [0] => string(13) "hello/"
  [1] => array(1) {
    ["name"] => int(2)
  }
  [2] => string(9) "localhost"
  [3] => NULL
  [4] => string(3) "get"
}

 3、通过容器中 rule_name 类 执行 set 方法,将解析的变量放入到 $this->item 属性中,

/**
     * 注册路由标识
     * @access public
     * @param  string   $name      路由标识
     * @param  array    $value     路由规则
     * @param  bool     $first     是否置顶
     * @return void
     */
    public function set($name, $value, $first = false)
    {
        if ($first && isset($this->item[$name])) {
            array_unshift($this->item[$name], $value);
        } else {
            $this->item[$name][] = $value;
        }
    }

 4、注册路由规则, 生成对应类型的变量。

    /**
     * 注册路由规则
     * @access public
     * @param  string   $rule      路由规则
     * @param  RuleItem $route     路由
     * @return void
     */
    public function setRule($rule, $route)
    {
        $this->rule[$route->getDomain()][$rule][$route->getMethod()] = $route;
    }
array(1) {
  ["localhost"] => array(1) {
    ["api"] => array(1) {
      ["get"] => object(think\route\RuleItem)#9 (10) {
        ["hasSetRule"] => NULL
        ["name"] => NULL
        ["rule"] => string(3) "api"
        ["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)
      }
    }
  }
}

 7、最后在定位到 RouteGroup 方法,执行 $this->RuleItem,并返回RouteItem 实列对象

        $this->addRuleItem($ruleItem, $method);

        return $ruleItem;

 

    public function addRuleItem($rule, $method = '*')
    {
        if (strpos($method, '|')) {
            $rule->method($method);
            $method = '*';
        }

        $this->rules[$method][] = $rule;

        return $this;
    }

   

array(8) {
  ["*"] => array(0) {
  }
  ["get"] => array(1) {
    [0] => object(think\route\RuleItem)#9 (10) {
      ["hasSetRule"] => bool(true)
      ["name"] => NULL
      ["rule"] => string(3) "api"
      ["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)
    }
  }
  ["post"] => array(0) {
  }
  ["put"] => array(0) {
  }
  ["patch"] => array(0) {
  }
  ["delete"] => array(0) {
  }
  ["head"] => array(0) {
  }
  ["options"] => array(0) {
  }
}

 

            

你可能感兴趣的:(php笔记,thinkphp,php应用,tp5框架源码分析)