thinkphp6.0 路由解析
三大件简述
1. 路由器 \think\Route
- 配置路由规则、管理所有路由规则和路由调度
2. 规则
导航当前操作到哪个路由
3. 路由
定义如何调度当前路由实现
核心类简述
项目 | 说明 |
---|---|
\think\Route | 路由器,专门做外部调度,比如添加路由、调度路由 |
\think\route\Rule | 路由规则基础类,抽象类,存储、匹配路由规则 |
|- \think\route\RuleGroup | 分组路由 是Rule的子类 |
|- \think\route\Domain | 按域名分组路由 默认是当前域名路由 是RuleGroup的子类 |
|- \think\route\RouteItem | 路由规则实体,每条规则都是一个对象,它是Rule的子类,以数组形式存储在RuleGroup中,RouteItem中自带一个check用于匹配路由规则,RuleGroup会枚举路由规则对象调用RouteItem->check |
\think\route\Dispatch | 路由调度运行 调度前会执行init()添加路由中间件 |
[:name] 、:name |
这类变量在添加时tp内部分别会转换成<name?>、<name>。参考源码:\think\Route->get() 、\think\route\RuleItem->setRule() |
<name> 、<name?> |
这类变量会在内部转换成((?<name>)pattern) 、((?<name>)pattern)? 的正则。其中pattern可以自己配置,否则自动引用系统默认的pattern( [\w\.]+ ),即默认生成的规则就是((?<name>)[\w\.]+) 、((?<name>)[\w\.]+)? 。参考源码:think\route\Rule->buildRuleRegex() 、think\route\Rule->buildNameRegex() |
路由调度
- 先获取app容器实例:
new App()
- 从app容器中得到http实例
app->http->run()
调度路由think\Route->dispatch()
think\Route->check()
:这里会调用域名分组路由(think\route\Domain
),然后think\route\Domain->check()
,最终会执行到think\route\Rule->check()
think\route\Rule->check()
:在这枚举当前分组路由的规则列表进行匹配url即think\route\RuleItem->check()
,如果匹配到当前url规则的路由会得到一个think\route\Dispatch
实例,然后退出枚举并return
这个实例。- 回到
think\Route->dispatch()
,这里check()
之后会得到上述的think\route\Dispatch
实例,然后think\route\Dispatch->init()
初始化调度器,初始化有两个作用,第一是注入app容器实例,第二是注册路由中间件。初始化完调度器后会通过管道模式执行think\route\Dispatch->run()
,其中路由中间件就会在这里的管道中被执行。 think\route\Dispatch->run()
:最后执行自身子类的exec()
,因为Dispatch有三个子类,分别是think\route\dispatch\Controller
、think\route\dispatch\Callback
,所以不同的场景有对应的实例:- 闭包、类方法路由:
think\route\dispatch\Callback
- 控制器方法:
think\route\dispatch\Controller
- 闭包、类方法路由:
think\route\dispatch\Callback
:这个比较简单,exec()只有映射函数的操作,效果类似call_user_function函数think\route\dispatch\Controller
:初始化过程中会根据路由规则解析出来的结果,分解成控制器、操作,最后配置到Request中。exec()会根据分解的结果通过映射来实现控制器调度。- 在调度器执行完映射后就得到Response实例,最后通过入口文件中调用
app->http->run()->send()
,将结果输出到浏览器。
总结
-
thinkphp6.0 路由解析
http://blog.icy8.cn/posts/62219/