项目目录相对为tp6
请求被统一转发到入口文件(入口文件地址为 tp6/index.php)
1.入口文件引入了composer自动载入文件类库
```
`<php?`
`namespace``think;`
`require``__DIR__ .``'/../vendor/autoload.php'``;`
```
(文件地址为 tp6/vendor/autoload.php')
2.实例化 think\\App 对象 赋值给$app
```
`<?php`
`$app``=``new``App();`
```
(App类文件地址为 tp6/vendor/topthink/framework/src/think/App.php')
执行App类中的\_\_construct构造方法
```
`<?php`
`public``function``__construct(string``$rootPath``=``''``)`
`{`
`// 框架类库目录`
`$this``->thinkPath = dirname(__DIR__) . DIRECTORY_SEPARATOR;`
`// 项目根目录`
`$this``->rootPath =``$rootPath``? rtrim(``$rootPath``, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR :``$this``->getDefaultRootPath();`
`// 应用目录`
`$this``->appPath =``$this``->rootPath .``'app'``. DIRECTORY_SEPARATOR;`
`// 项目缓存目录`
`$this``->runtimePath =``$this``->rootPath .``'runtime'``. DIRECTORY_SEPARATOR;`
`// 加载服务provide容器`
`if``(``is_file``(``$this``->appPath .``'provider.php'``)) {`
`// 执行 Container\bind()方法 绑定类、闭包、实例、接口`
`$this``->bind(``include``$this``->appPath .``'provider.php'``);`
`}`
`// 设置一个容器实例`
`static``::setInstance(``$this``);`
`// 绑定类的实例到容器`
`$this``->instance(``'app'``,``$this``);`
`$this``->instance(``'think\Container'``,``$this``);`
`}`
```
其中在属性$bind中已经有了一些框架类的别名与实现的映射数组
此时$app因为是继承了Container类,所以$app实际也是一个容器
3.通过$app类调用http类(web管理类)
```
`$http``=``$app``->http;`
```
3.0 引用http类的过程如下:
(http类文件地址为 tp6/vendor/topthink/framework/src/think/Http.php')
3.1 首先App中不存在http方法,但是在容器类中存在魔术方法\_\_get,会触发该魔术方法
```
`<?php`
`public``function``__get(``$name``)`
`{`
`return``$this``->get(``$name``);`
`}`
```
get方法从app应用容器中获取http对象实例
```
`<php?`
`/**`
`* 获取容器中的对象实例`
`* @access public`
`* @param string $abstract 类名或者标识`
`* @return object`
`*/`
`public``function``get(``$abstract``)`
`{`
`if``(``$this``->has(``$abstract``)) {`
`return``$this``->make(``$abstract``);`
`}`
`throw``new``ClassNotFoundException(``'class not exists: '``.``$abstract``,``$abstract``);`
`}`
```
3.2 通过app应用容器中的make方法进行类的实例,以及执行instances方法将实例化的http类绑定到容器数组对象中
```
`<?php`
`/**`
`* 创建类的实例 已经存在则直接获取`
`* @access public`
`* @param string $abstract 类名或者标识`
`* @param array $vars 变量`
`* @param bool $newInstance 是否每次创建新的实例`
`* @return mixed`
`*/`
`public``function``make(string``$abstract``,``array``$vars``= [], bool``$newInstance``= false)`
`{`
`$abstract``=``$this``->getAlias(``$abstract``);`
`if``(isset(``$this``->instances[``$abstract``]) && !``$newInstance``) {`
`return``$this``->instances[``$abstract``];`
`}`
`if``(isset(``$this``->bind[``$abstract``]) &&``$this``->bind[``$abstract``]``instanceof``Closure) {`
`$object``=``$this``->invokeFunction(``$this``->bind[``$abstract``],``$vars``);`
`}``else``{`
`$object``=``$this``->invokeClass(``$abstract``,``$vars``);`
`}`
`if``(!``$newInstance``) {`
`$this``->instances[``$abstract``] =``$object``;`
`}`
`return``$object``;`
`}`
```
返回http对象实例到调用处 第3步开始的地方
4 http对象执行run方法,应用程序的执行开始
```
`<?php`
`/**`
`* 执行应用程序`
`* @access public`
`* @param Request|null $request`
`* @return Response`
`*/`
`public``function``run(Request``$request``= null): Response`
`{`
`//自动创建request对象`
`$request``=``$request``??``$this``->app->make(``'request'``, [], true);`
`// 绑定request类的实例化对象到容器中`
`$this``->app->instance(``'request'``,``$request``);`
`try``{`
`// 执行应用程序返回response类`
`$response``=``$this``->runWithRequest(``$request``);`
`}``catch``(Throwable``$e``) {`
`$this``->reportException(``$e``);`
`$response``=``$this``->renderException(``$request``,``$e``);`
`}`
`return``$response``;`
`}`
```
4.1 run 方法中首先创建Request类,执行instances方法将实例化的Request类绑定到容器数组对象中,标识为request
然后进行路由调度,执行 app容器中runWithRequest方法
```
`/**`
`* 执行应用程序`
`* @param Request $request`
`* @return mixed`
`*/`
`protected``function``runWithRequest(Request``$request``)`
`{`
`// 初始化app应用程序`
`$this``->initialize();`
`// 加载全局中间件`
`$this``->loadMiddleware();`
`// 监听HttpRun`
`$this``->app->event->trigger(HttpRun::``class``);`
`// 中间件调度`
`return``$this``->app->middleware->pipeline()`
`->send(``$request``)`
`->then(``function``(``$request``) {`
`return``$this``->dispatchToRoute(``$request``);`
`});`
`}`
```
4.2然后在在http类中runWithRequest方法中执行了dispatchToRoute 讲请求分发到路由
(dispatchToRoute 类方法的文件地址为 tp6/vendor/topthink/framework/src/think/Route.php')
// 分发请求到路由
```
`<?php`
`protected``function``dispatchToRoute(``$request``)`
`{`
`// 是否启用路由, 默认启用路由`
`$withRoute``=``$this``->app->config->get(``'app.with_route'``, true) ?``function``() {`
`$this``->loadRoutes();`
`} : null;`
`// 执行路由调度`
`return``$this``->app->route->dispatch(``$request``,``$withRoute``);`
`}`
```
4.3 在http类中dispatchToRoute 通过app容器获取了route实例,并调用了route实例中的dispatch方法
```
<?php
/\*\*
\* 路由调度
\* @param Request $request
\* @param Closure|bool $withRoute
\* @return Response
\*/
public function dispatch(Request $request, $withRoute = true)
{
$this->request = $request;
$this->host = $this->request->host(true);
$this->init();
if ($withRoute) {
// 加载路由设置
if ($withRoute instanceof Closure) {
$withRoute();
}
// 检查路由
$dispatch = $this->check();
} else {
// 如果没有路由,则使用默认url解析
$dispatch = $this->url($this->path());
}
// $dispatch 为think\\route\\dispatch\\Controller 的实例化 中的初始化,提取控制名称以及操作名称
// 1, 通过最终think\\route\\Rule::dispatch来确路由调度的最终执行动作
$dispatch->init($this->app);
return $this->app->middleware->pipeline('route')
->send($request)
->then(function () use ($dispatch) {
// 执行动作方法
return $dispatch->run();
});
}
```
4.4 在route类中的dispatch中执行了run方法,
(run 类方法的文件地址为 tp6/vendor/topthink/framework/src/think/route/Dispatch.php')
```
`<?php<br>``/**`
`* 执行路由调度`
`* @access public`
`* @return mixed`
`*/`
`public``function``run(): Response`
`{`
`if``(``$this``->rule``instanceof``RuleItem &&``$this``->request->method() ==``'OPTIONS'``&&``$this``->rule->isAutoOptions()) {`
`$rules``=``$this``->rule->getRouter()->getRule(``$this``->rule->getRule());`
`$allow``= [];`
`foreach``(``$rules``as``$item``) {`
`$allow``[] =``strtoupper``(``$item``->getMethod());`
`}`
`return``Response::create(``''``,``'html'``, 204)->header([``'Allow'``=> implode(``', '``,``$allow``)]);`
`}`
`// 此处调用的$this类,由调用者确定, 可能为url, callback, 或者controller`
`// $data 为返回的response 类`
`$data``=``$this``->``exec``();`
`return``$this``->autoResponse(``$data``);`
`}`
```
4.5 run方法调用了exec
(此处调用的exec的类方法所在的文件,由调用者确定, 可能为url, callback, 或者controller, exec 类方法的文件地址为 tp6/vendor/topthink/framework/src/think/route/dispatch/Callback.php|Controller.php')
在exec方法中最终返回了data数据
4.6 然后调用了autoResponse方法,并传递4.5返回的data数据
(autoResponse 类方法的文件地址为 tp6/vendor/topthink/framework/src/think/route/Dispatch.php')
```
`<?php`
`protected``function``autoResponse(``$data``): Response`
`{`
`if``(``$data``instanceof``Response) {`
`$response``=``$data``;`
`}``elseif``(!``is_null``(``$data``)) {`
`// 默认自动识别响应输出类型`
`$type` `=``$this``->request->isJson() ?``'json'``:``'html'``;`
`$response``= Response::create(``$data``,``$type``);`
`}``else``{`
`$data``= ob_get_clean();`
`$content` `= false ===``$data``?``''``:``$data``;`
`$status` `=``''``===``$content``&&``$this``->request->isJson() ? 204 : 200;`
`// 创建response类返回,使用html`
`$response``= Response::create(``$content``,``'html'``,``$status``);`
`}`
`return``$response``;`
`}`
```
4.7 autoResponse 方法中执行了 Response::create方法
最终方法返回了response对象;
(Response::create 类方法的文件地址为 tp6/vendor/topthink/framework/src/think/Response.php')
```
`<?php`
`/**`
`* 创建Response对象`
`* @access public`
`* @param mixed $data 输出数据`
`* @param string $type 输出类型`
`* @param int $code 状态码`
`* @return Response`
`*/`
`public``static``function``create(``$data``=``''``, string``$type``=``'html'``, int``$code``= 200): Response`
`{`
`$class``= false !==``strpos``(``$type``,``'\\'``) ?``$type``:``'\\think\\response\\'``. ucfirst(``strtolower``(``$type``));`
`return``Container::getInstance()->invokeClass(``$class``, [``$data``,``$code``]);`
`}`
```
4.8 最终返回了 response Html类的对象实例
5 执行run方法
```
`$response``=``$http``->run();`
```
6 response 执行send输出数据的操作;
(Html 类文件所在地址为 tp6/vendor/topthink/framework/src/think/response/Html.php )
6.1 执行send方法
(send方法 类文件所在地址为 tp6/vendor/topthink/framework/src/think/Response.php )
$response->send();
```
`<?php`
`/**`
`* 发送数据到客户端`
`* @access public`
`* @return void`
`* @throws \InvalidArgumentException`
`*/`
`public``function``send(): void`
`{`
`// 处理输出数据`
`$data``=``$this``->getContent();`
`if``(!headers_sent() && !``empty``(``$this``->header)) {`
`// 发送状态码`
`http_response_code(``$this``->code);`
`// 发送头部信息`
`foreach``(``$this``->header``as``$name``=>``$val``) {`
`header(``$name``. (!``is_null``(``$val``) ?``':'``.``$val``:``''``));`
`}`
`}`
`if``(``$this``->cookie) {`
`$this``->cookie->save();`
`}`
`$this``->sendData(``$data``);`
`if``(function_exists(``'fastcgi_finish_request'``)) {`
`// 提高页面响应`
`fastcgi_finish_request();`
`}`
`}`
```
6.1 在send方法中最终执行了 sendData 方法
(sendData方法 类文件所在地址为 tp6/vendor/topthink/framework/src/think/Response.php )
```
`<?php`
`/**`
`* 输出数据`
`* @access protected`
`* @param string $data 要处理的数据`
`* @return void`
`*/`
`protected``function``sendData(string``$data``): void`
`{`
`echo``$data``;`
`}`
```
7 执行 http对象中的end方法
```
`<?php`
`$http``->``end``(``$response``);`
```
(http类文件地址为 tp6/vendor/topthink/framework/src/think/Http.php')
```
`<?php`
`/**`
`* HttpEnd`
`* @param Response $response`
`* @return void`
`*/`
`public``function``end``(Response``$response``): void`
`{`
`$this``->app->event->trigger(HttpEnd::``class``,``$response``);`
`//执行中间件`
`$this``->app->middleware->``end``(``$response``);`
`// 写入日志`
`$this``->app->log->save();`
`}`
```
8整个程序结束
应用类App继承了Container容器类, 所有类的实例通过容器类进行统一管理,容器类为单例模式全局唯一;
![](https://img.kancloud.cn/12/6e/126ee53d8e0378f737432c5c93a17b62_1511x1600.jpg)
- thinkphp6执行流程(一)
- php中use关键字用法详解
- Thinkphp6使用腾讯云发送短信步骤
- 路由配置
- Thinkphp6,static静态资源访问路径问题
- ThinkPHP6.0+ 使用Redis 原始用法
- smarty在thinkphp6.0中的最佳实践
- Thinkphp6.0 搜索器使用方法
- 从已有安装包(vendor)恢复 composer.json
- tp6with的用法,表间关联查询
- thinkphp6.x多对多如何添加中间表限制条件
- thinkphp6 安装JWT
- 缓存类型
- 请求信息和HTTP头信息
- 模型事件用法
- 助手函数汇总
- tp6集成Alipay 手机和电脑端支付的方法
- thinkphp6使用jwt
- 6.0session cookie cache
- tp6笔记
- TP6(thinkphp6)队列与延时队列
- thinkphp6 command(自定义指令)
- command(自定义指令)
- 本地文件上传
- 缓存
- 响应
- 公共函数配置
- 七牛云+文件上传
- thinkphp6:访问多个redis数据源(thinkphp6.0.5 / php 7.4.9)
- 富文本编辑器wangEditor3
- IP黑名单
- 增删改查 +文件上传
- workerman 定时器操作控制器的方法
- 上传文件到阿里云oss
- 短信或者邮箱验证码防刷代码
- thinkphp6:访问redis6(thinkphp 6.0.9/php 8.0.14)
- 实现关联多个id以逗号分开查询数据
- thinkphp6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 用mpdf生成pdf文件(php 8.1.1 / thinkphp v6.0.10LTS )
- 生成带logo的二维码(php 8.1.1 / thinkphp v6.0.10LTS )
- mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
- 一,创建过滤IP的中间件
- 源码解析请求流程
- 验证码生成
- 权限管理
- 自定义异常类
- 事件监听event-listene
- 安装与使用think-addons
- 事件与多应用
- Workerman 基本使用
- 查询用户列表按拼音字母排序
- 扩展包合集
- 查询用户数据,但是可以通过输入用户昵称来搜索用户同时还要统计用户的文章和粉丝数
- 根据图片的minetype类型获取文件真实拓展名思路
- 到处excel
- 用imagemagick库生成缩略图
- 生成zip压缩包并下载
- API 多版本控制
- 用redis+lua做限流(php 8.1.1 / thinkphp v6.0.10LTS )
- 【thinkphp6源码分析三】 APP类之父, 容器Container类
- thinkphp6表单重复提交解决办法
- 小程序授权
- 最简单的thinkphp6导出Excel
- 根据访问设备不同访问不同模块
- 服务系统
- 前置/后置中间件
- 给接口api做签名验证(php 8.1.1 / thinkphp v6.0.10LTS )
- 6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 使用前后端分离的验证码(thinkphp 6.0.9/php 8.0.14/vue 3.2.26)
- 前后端分离:用jwt+middleware做用户登录验证(php 8.1.1 / thinkphp v6.0.10LTS )
- vue前后端分离多图上传
- thinkphp 分组、页面跳转与ajax
- thinkphp6 常用方法文档
- 手册里没有的一些用法
- Swagger 3 API 注释
- PHP 秒级定时任务
- thinkphp6集成gatewayWorker(workerman)实现实时监听
- thinkphp6按月新增数据表
- 使用redis 实现消息队列
- api接口 统一结果返回处理类
- 使用swoole+thinkphp6.0+redis 结合开发的登录模块
- 给接口api做签名验证
- ThinkPHP6.0 + UniApp 实现小程序的 微信登录
- ThinkPHP6.0 + Vue + ElementUI + axios 的环境安装到实现 CURD 操作!
- 异常$e
- 参数请求验证自定义和异常错误自定义