30
07月
2020
public/index.php
<?php ...... // 执行应用并响应 Container::get('app')->run()->send();
Container:: get('app')最终将指向了 think\App.php类,run()内部首先调用了initialize();
thinkphp/library/think/App.php
<?php ...... /** * 执行应用程序 * @access public * @return Response * @throws Exception */ public function run() { try { // 初始化应用 $this->initialize(); ...... } ...... } /** * 初始化应用 * @access public * @return void */ public function initialize() { ...... // 路由初始化 $this->routeInit(); }
routeInit()会读取route目录下的所有路由文件, 判断路由文件的返回值,从而进行不同的处理
thinkphp/library/think/App.php
/** * 路由初始化 导入路由定义规则 * @access public * @return void */ public function routeInit() { // 路由检测 $files = scandir($this->routePath); foreach ($files as $file) { if (strpos($file, '.php')) { $filename = $this->routePath . $file; // 导入路由配置 $rules = include $filename; if (is_array($rules)) { $this->route->import($rules); } } } if ($this->route->config('route_annotation')) { // 自动生成路由定义 if ($this->appDebug) { $suffix = $this->route->config('controller_suffix') || $this->route->config('class_suffix'); $this->build->buildRoute($suffix); } $filename = $this->runtimePath . 'build_route.php'; if (is_file($filename)) { include $filename; } } }
路由文件,通过门面模式找到了facade/route类,并调用其get方法
route/route.php
<?php Route::get('think', function () { return 'hello,ThinkPHP5!'; }); Route::get('hello/:name', 'index/hello'); return [ ];
官方手册示例如下
Route::get('new/:id','News/read'); // 定义GET请求路由规则 Route::post('new/:id','News/update'); // 定义POST请求路由规则 Route::put('new/:id','News/update'); // 定义PUT请求路由规则 Route::delete('new/:id','News/delete'); // 定义DELETE请求路由规则 Route::any('new/:id','News/read'); // 所有请求都支持的路由规则 如果要定义get和post请求支持的路由规则,也可以用 Route::get('new/:id','News/read','GET|POST');
无论是get() 还是 post() 还是 rule(),其本质都是调用 addRule()
thinkphp/library/think/Route.php
<?php class Route { ...... /** * 注册路由规则 * @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); } ...... }
thinkphp/library/think/route/RuleGroup.php
<?php class RuleGroup extends Rule { /** * 添加分组下的路由规则或者子分组 * @access public * @param string $rule 路由规则 * @param string $route 路由地址 * @param string $method 请求类型 * @param array $option 路由参数 * @param array $pattern 变量规则 * @return $this */ public function addRule($rule, $route, $method = '*', $option = [], $pattern = []) { // 读取路由标识 if (is_array($rule)) { $name = $rule[0]; $rule = $rule[1]; } elseif (is_string($route)) { $name = $route; } else { $name = null; } $method = strtolower($method); if ('/' === $rule || '' === $rule) { // 首页自动完整匹配 $rule .= '$'; } // 创建路由规则实例 $ruleItem = new RuleItem($this->router, $this, $name, $rule, $route, $method, $option, $pattern); if (!empty($option['cross_domain'])) { $this->router->setCrossDomainRule($ruleItem, $method); } $this->addRuleItem($ruleItem, $method); return $ruleItem; } }
new RuleItem 会创建路由规则实例
thinkphp/library/think/route/RuleItem.php
<?php class RuleItem extends Rule { ...... /** * 架构函数 * @access public * @param Route $router 路由实例 * @param RuleGroup $parent 上级对象 * @param string $name 路由标识 * @param string|array $rule 路由规则 * @param string|\Closure $route 路由地址 * @param string $method 请求类型 * @param array $option 路由参数 * @param array $pattern 变量规则 */ public function __construct(Route $router, RuleGroup $parent, $name, $rule, $route, $method = '*', $option = [], $pattern = []) { $this->router = $router; $this->parent = $parent; $this->name = $name; $this->route = $route; $this->method = $method; $this->option = $option; $this->pattern = $pattern; $this->setRule($rule); if (!empty($option['cross_domain'])) { $this->router->setCrossDomainRule($this, $method); } } /** * 路由规则预处理 * @access public * @param string $rule 路由规则 * @return void */ public function setRule($rule) { if ('$' == substr($rule, -1, 1)) { // 是否完整匹配 $rule = substr($rule, 0, -1); $this->option['complete_match'] = true; } $rule = '/' != $rule ? ltrim($rule, '/') : ''; if ($this->parent && $prefix = $this->parent->getFullName()) { $rule = $prefix . ($rule ? '/' . ltrim($rule, '/') : ''); } if (false !== strpos($rule, ':')) { $this->rule = preg_replace(['/\[\:(\w+)\]/', '/\:(\w+)/'], ['<\1?>', '<\1>'], $rule); } else { $this->rule = $rule; } // 生成路由标识的快捷访问 $this->setRuleName(); } ...... }