在现代 PHP 开发中,框架的启动流程往往决定了应用的性能上限。Restina 框架通过精简的代码结构,实现了从请求入口到业务逻辑的高效流转。本文将结合源码,详细追踪一个请求从抵达服务器到生成响应的五个核心阶段。
第一阶段:入口引导与环境探测
文件:public/index.php
所有的请求都统一指向 public/index.php,这是整个应用的“唯一入口”。
- 自动加载:
require_once __DIR__ . '/../vendor/autoload.php';引入 Composer 的自动加载机制,这是现代 PHP 框架的基础。
- 门面启动:
- 代码调用
App::init()->boot()->run()->end();。这是一个典型的流式接口(Fluent Interface)设计,通过链式调用将四个核心阶段串联起来。
- 代码调用
深入 App->__construct():
在 init() 调用时,构造函数会立即执行两个底层操作:
- 路径初始化 (
initializePaths):框架通过dirname()多层嵌套,精准定位项目根目录、app目录、runtime目录。这是框架“约定优于配置”的体现。 - 运行模式探测 (
determineRunMode):- Worker 模式:优先检测
frankenphp_handle_request函数或环境变量,适用于常驻内存的高性能场景。 - CLI 模式:检测
PHP_SAPI,用于命令行任务。 - CGI 模式:默认模式,适用于传统 FPM。
- Worker 模式:优先检测
第二阶段:核心服务注册与依赖注入
方法:App->boot()
这是框架的“组装车间”。在此阶段,框架通过依赖注入容器(DI Container)来管理对象的生命周期。
- 配置加载 (
loadAppConfiguration):- 框架读取
app/config.php。值得注意的是,Restina 在这里直接将配置数组赋值给Config类属性,简单直接。
- 框架读取
- 错误处理接管 (
setDebugMode):- 关键细节:框架使用
set_exception_handler和set_error_handler将错误处理权完全交给App类的handleUncaughtException和handlePhpError方法。这意味着无论代码中发生什么错误,最终都会被框架捕获并格式化,保证了 API 返回的统一性。
- 关键细节:框架使用
- 核心组件绑定 (
registerCoreServices):- 框架实例化了日志 (
Logger)、缓存 (Cache)、数据库 (Db)、JWT 等核心对象。 - 容器注入:这些对象被放入
Container中。通过bindCoreServicesToContainer,开发者可以在任何地方通过$app->db或$app->cache获取到这些服务的单例。
- 框架实例化了日志 (
第三阶段:路由编译与注解扫描
方法:App->run() 内部调用
这是 Restina 框架最具特色的环节——注解驱动路由。
- 路由收集策略:
- 开发环境 (Debug):每次请求都会实时扫描
app/controllers目录,利用 PHP 8 的 Reflection API 解析 #[Route(methods: [‘POST’], path: ‘/admin/auth/login’, code: ‘admin.auth.login’, permission: false, jwt: false, autoRefreshToken: true)] Attributes 注解。 - 生产环境 (Production):框架会先尝试从缓存(Redis 或文件)中读取键名为
routes的数据。- 源码细节:如果缓存未命中,框架才会执行扫描,并将结果缓存 86400 秒(24小时)。
- 开发环境 (Debug):每次请求都会实时扫描
- 路由注册:
- 解析出的路由规则(URI -> Controller::Method)被传递给
Http实例的registerRoutes方法,构建内存路由表。
- 解析出的路由规则(URI -> Controller::Method)被传递给
第四阶段:请求分发与中间件管道
方法:App->handleRequest()
当路由准备就绪后,框架进入请求处理的核心逻辑。
- 中间件管道 (
Hook::runPipe):- Restina 利用 Hook(钩子)系统实现了中间件。源码中
Hook::runPipe('request.middleware', ...)表明,框架会依次执行注册在request.middleware上的所有逻辑(如 CORS 头处理、身份验证)。 - 只有当所有中间件都“放行”后,才会执行闭包内的
Router->dispatch()。
- Restina 利用 Hook(钩子)系统实现了中间件。源码中
- 路由分发 (
Router->dispatch):- 路由器根据当前请求的 URL 和 Method 匹配路由表。
- 依赖注入:匹配成功后,框架利用容器自动解析控制器方法所需的参数(如
Request对象、服务类),并执行该方法,返回一个Response对象。
第五阶段:响应输出与资源回收
方法:App->end()
这是请求周期的终点,也是资源清理的起点。
- 运行时适配:
- Worker 模式:利用
frankenphp_handle_request的回调机制,保持连接长存。 - CGI 模式:直接调用
$response->send()发送 HTTP 头和正文。 - CLI 模式:输出内容到控制台。
- Worker 模式:利用
- 优雅终止 (
end方法):- 连接管理:如果是非 Worker 模式且使用了 Redis,框架会主动调用
$this->cache->close()关闭连接,防止连接池泄露。 - 日志刷盘:调用
$this->logger->write()。这意味着日志可能是在请求结束时才批量写入文件,这种“延迟写入”策略能显著减少 IO 次数,提升高并发下的性能。
- 连接管理:如果是非 Worker 模式且使用了 Redis,框架会主动调用
总结
Restina 框架的执行流程体现了“微内核”的设计思想:
- 单一入口确保了逻辑的集中控制。
- 注解路由极大地简化了开发体验,配合缓存机制消除了反射性能损耗。
- 全链路接管(错误处理、响应发送)保证了应用的健壮性和一致性。
0