路由有关的类
RuleItem类,路由规则类,继承Rule类,一条路由规则就实例化一个RuleItem类,Rule::get()返回的就是RuleItem实例。
1、重要属性
$rule:路由规则字符串
$name:路由标识
$router:Router对象
$vars:传参的参数数组
$option:路由参数,多维数组,例如middleware。
check().这个就是根据访问的url等信息,匹配路由规则实例,如果匹配上,返回Module类对象,后面就是Module对象执行调度方法实现控制器和方法的执行。
RuleGroup类,分组路由,继承Rule类
$this->rules[],分类存放RuleItem对象。路由导入就是注册到到这个对象中。
check(),通过request对象得到请求方式get,post,遍历这个分组下面的所有RuleItem对象,执行RuleItem->check()。如果匹配上,会返回Module类对象,保存着匹配的信息。
Route类,路由类,操作路由规则对象的类,依赖RuleGroup类
get(),post()...依赖RuleGroup实例,导入路由对象
Module类,继承Dispatch,其实就是执行调度的类。
1、重要属性
$controller:访问的控制器名
$actionName:方法名
$request:Request对象,
$rule:RuleItem对象
2.重要的方法有
run()执行路由调度
TP5.1如何实现路由
1.路由规则导入,初始化应用initialize()的时候会启动路由初始化
扫描route目录下的所有文件,include进来,并且把数组import
// 导入路由配置
$rules = include $filename;
if (is_array($rules)) {
$this->route->import($rules);
}
如果使用 Route::get('hello/:name', 'index/hello');则通过Route对象的get导入路由规则$this->group->addRule($rule, $route, $method, $option, $pattern);实质就是RuleGroup对象调用addRule方法
Route::get()返回的是RuleItem实例,所以后面的middle(),cache()等方法,都是调用RuleItem实例的方法。
1.创建路由规则实例RuleItem对象(一条路由就生成一条路由规则对象)
2.加入到RuleGroup类的属性$this->rules[$method] []= $ruleItem;以method为键
2.得到Module对象,并执行init方法
if (empty($dispatch)) {
// 路由检测
$dispatch = $this->routeCheck()->init();
}
public function __construct(Request $request, Rule $rule, $dispatch, $param = [], $code = null)
{
$this->request = $request;
$this->rule = $rule;
$this->app = Container::get('app');
$this->dispatch = $dispatch;
$this->param = $param;
$this->code = $code;
if (isset($param['convert'])) {
$this->convert = $param['convert'];
}
}
控制器的执行
在app的run方法中,下面这段就是执行控制器方法,从路由匹配中获取到Module对象,然后调用run方法,返回Response对象。
$this->middleware->add(function (Request $request, $next) use ($dispatch, $data) {
return is_null($data) ? $dispatch->run() : $data;
});
最终执行的是Module对象的exec()方法,获取到类名,通过容器实例化对象,然后通过反射执行对应的方法。
// 实例化控制器
$instance = $this->app->controller($this->controller,
$this->rule->getConfig('url_controller_layer'),
$this->rule->getConfig('controller_suffix'),
$this->rule->getConfig('empty_controller'));
//获取控制器方法的反射
$reflect = new ReflectionMethod($instance, $action);
//执行方法,返回方法的返回值
$data = $this->app->invokeReflectMethod($instance, $reflect, $vars);
//把返回值传入autoResponse生成Response对象
$response = Response::create($data, $type);
//根据type的类型,使用不同的类
public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
{
$class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst(strtolower($type));
if (class_exists($class)) {
return new $class($data, $code, $header, $options);
}
return new static($data, $code, $header, $options);
}
数据的返回
Response方法调用send输出内容
会判断符合的数据格式为null,string,number, is_callable([ $content, '__toString', ]).其他数据格式会报variable type error。所以控制器的方法return 的数据需要以上的格式才行。
然后echo $data,把数据放入php的输出缓存中。进程结束后php会把缓存的数据返回给nginx。
echo
echo
不是一个函数,是一个PHP的语言结构,输出基本数据类型和对象(需要定义__toString魔术方法,不然会报错);
php输出缓存output_buffering
通过配置文件开启output_buffering = on, 默认打开,还可以设置大小。