|
|
楼主 |
发表于 2025-9-1 11:14:57
|
显示全部楼层
详细源码流程分析(基于 TP6.0+ 源码)
1. 入口文件:public/index.php
<?php
// 定义应用目录
define('APP_PATH', __DIR__ . '/../app/');
// 加载 Composer 自动加载
require __DIR__ . '/../vendor/autoload.php';
// 执行应用
(new \think\App())->run()->send();
✅ 这是所有请求的统一入口,遵循“单一入口”原则。
2. new App():初始化应用容器
文件:thinkphp/library/think/App.php
public function __construct(string $rootPath = '')
{
$this->instance('app', $this);
$this->instance('think\Container', $this);
$this->rootPath = $rootPath ?: dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
$this->bind([
// 绑定核心类
'app' => self::class,
'container' => Container::class,
]);
}
关键动作:
创建服务容器(Container),自身也注册为单例。
设置项目根目录。
绑定核心类到容器。
3. $app->run():启动应用
public function run()
{
try {
// 初始化基础环境
$this->initialize();
// 路由调度
$dispatch = $this->routeCheck();
// 执行调度(进入中间件和控制器)
$data = $this->dispatch($dispatch);
} catch (Throwable $e) {
$data = $this->render($e);
}
// 包装为 Response 对象
return $this->response($data);
}
4. $this->initialize():初始化阶段
protected function initialize()
{
// 设置错误处理
$this->setDebugMode();
$this->setExceptionHandler();
// 加载环境变量(.env)
$this->loadEnv();
// 注册服务提供者
$this->registerServiceProviders();
// 加载配置文件(config/*.php)
$this->loadConfigFiles();
// 注册核心门面
$this->registerFacades();
}
关键动作:
加载 .env 环境变量
注册服务提供者(ServiceProvider)
遍历 config/app.php 中的 providers,调用每个服务的 register() 方法,将服务绑定到容器。
php
深色版本
'providers' => [
think\service\CacheService::class,
think\service\EventService::class,
]
加载配置文件:将 config/*.php 文件合并到 Config 实例中。
注册门面(Facade):为 Cache, Log 等提供静态代理。
5. $this->routeCheck():路由解析
protected function routeCheck()
{
// 读取路由规则(来自 route/app.php)
$rules = include $this->getRoutePath() . 'app.php';
// 创建路由对象
$this->route = new Route($this);
// 导入路由规则
$this->route->import($rules);
// 请求对象
$request = $this->request;
// 路由调度:解析 URL → 找到控制器和方法
return $this->route->dispatch($request);
}
路由匹配流程:
根据请求方法(GET/POST)和路径(如 /user/123)匹配路由规则。
支持闭包路由、控制器路由、资源路由。
生成 Dispatch 对象(可能是 Module, Controller, Callback 类型)。
✅ 路由缓存:如果启用了路由缓存,会直接读取 runtime/route_cache.php,跳过解析。
6. $this->dispatch($dispatch):执行调度
protected function dispatch($dispatch)
{
// 创建中间件栈
$middleware = $this->middleware->import();
// 推入全局中间件
foreach ($middleware as $item) {
$this->middleware->push($item);
}
// 执行中间件 + 最终调用控制器
return $this->middleware->dispatch($dispatch);
}
7. 中间件执行:Middleware->dispatch()
文件:think/Middleware.php
public function dispatch($dispatch)
{
$next = function ($dispatch) use (&$next) {
// 这是“最终处理器”:调用控制器
return $this->handler($dispatch);
};
// 从后往前封装中间件(洋葱模型)
while ($stack = array_pop($this->queue)) {
$next = function () use ($stack, $next) {
return $stack->handle($this->request, $next);
};
}
return $next($dispatch);
}
洋葱模型(Onion Model):
深色版本
Request → Middleware 3 → Middleware 2 → Middleware 1 → Controller
↑ ↑ ↑
Response ← Middleware 3 ← Middleware 2 ← Middleware 1 ← Controller
✅ 中间件通过闭包嵌套实现“环绕执行”。
8. $this->handler($dispatch):调用控制器
protected function handler($dispatch)
{
if ($dispatch instanceof ControllerDispatch) {
[$controller, $action] = $this->parseControllerAndAction($dispatch);
// 从容器创建控制器(自动注入依赖)
$instance = $this->app->make($controller);
// 调用控制器方法
return call_user_func([$instance, $action], $this->request);
}
}
控制器依赖注入示例:
class UserController
{
public function __construct(private UserService $userService) {}
public function index()
{
return $this->userService->getList(); // 自动注入
}
}
✅ 容器自动解析构造函数依赖,实现 DI。
9. 控制器返回数据 → 生成响应
控制器可以返回:
字符串
数组(自动转 JSON)
Response 对象
视图(View)
// TP6 自动包装为 Response
return json(['name' => 'thinkphp']);
// 等价于
return Response::create(['name' => 'thinkphp'], 'json');
10. $app->response($data):包装响应
protected function response($data): Response
{
if (!$data instanceof Response) {
// 根据内容类型自动创建 Response
$type = $this->request->getResponseFormat();
$data = Response::create($data, $type);
}
return $data;
}
11. ->send():发送响应并结束
public function send()
{
// 发送 HTTP 头
$this->sendHeader();
// 发送内容
echo $this->getContent();
// 触发响应结束事件
$this->app->event->trigger('ResponseEnd');
// 结束
exit;
} |
|