fiberphp / framework
FiberPHP framework core: application lifecycle orchestration, config management, service providers, package discovery.
No longer found in upstream repository
Requires
- php: >=8.3
- ext-json: *
- ext-pcntl: *
- ext-posix: *
- fiberphp/container: dev-master
- psr/log: ^3.0
- revolt/event-loop: ^1.0
- workerman/workerman: ^5.1
Requires (Dev)
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-08-22 10:25:31 UTC
README
基于 Workerman 5.x 的应用框架内核,提供应用生命周期编排、配置管理、服务提供者(Provider)两阶段启动、包发现(Package Manifest)等能力。
- PHP >= 8.3
- 系统:Linux / macOS(依赖
pcntl扩展,不支持 Windows) - 依赖:
workerman/workerman ^5.1、fiberphp/container dev-master、psr/log ^3.0
目录结构
framework/
├── composer.json
└── src/
├── App.php # 运行时门面:项目入口唯一调用点
├── Kernel.php # 应用生命周期编排器(主进程/Worker 引导)
├── Config.php # 配置加载与点分取值(含编译缓存)
├── Env.php # .env 解析与环境变量管理(env/env_int)
├── Context.php # 请求级上下文容器(键值存取 + onDestroy 生命周期回调)
├── WorkerFactory.php # Worker 进程创建与事件回调绑定(Workerman 运行时专用)
├── PackageManifest.php # 统一包发现清单(middleware/commands/providers/aliases)
├── PackageInstaller.php # Composer 钩子执行者(post-autoload-dump / uninstall,含配置文件拷贝)
├── helpers.php # 全局函数(path_*, config, app, logger fallback ...)
├── Logger.php # 框架自带最小 Logger 实现(logger() 兜底,JSON 格式输出)
├── Pipeline.php # 中间件管道构建器(洋葱模型,静态 build() 方法)
├── Attribute/
│ └── Package.php # 子包扩展点声明 Attribute(pathRelation/providers/...)
├── Bootstrap/
│ ├── BootGuard.php # boot 阶段守卫(pcntl_alarm 超时保护 + 异常降级策略)
│ └── Sorter.php # Provider 拓扑排序(Kahn 算法 + app.boot_order)
├── Contract/
│ ├── BootstrapInterface.php # 自定义引导步骤契约(子包注入 master/worker 引导)
│ └── ProviderInterface.php # 服务提供者契约(register / boot / bootMeta / bootAfter)
└── Exception/
├── Exception.php # 异常基类(debug 数据 + boot 渲染)
├── Handler.php # 统一异常处理基类(render/report/handle/resolve)
└── BusinessException.php # 业务异常标签
核心组件
App — 运行时门面
App.php 是项目入口文件(如 start.php)的唯一调用点,提供多种运行模式,所有模式共用同一套 Kernel 生命周期:
| 方法 | 用途 | 是否 fork Worker | 是否进入事件循环 |
|---|---|---|---|
run() | 生产启动(php start.php start) | 是 | 是 |
bootstrap() | 一次性 CLI 脚本 / Cron / PHPUnit 测试 | 否 | 否 |
runWithConfig($cfg) | 嵌入式 / 微服务(跳过 config 扫描) | 是 | 是 |
run() 会扫描 config/process/*.php,合并为进程配置后交给 WorkerFactory::start(),最后调用 Worker::runAll()。重名进程会抛 RuntimeException。
Kernel — 生命周期编排器
Kernel.php 是单例,纯编排职责:"在正确的时机调用正确的步骤"。职责被拆解到独立类:
- Provider 依赖拓扑排序 → Sorter
- boot 超时保护与异常策略 → BootGuard
- Worker 创建与回调绑定 → WorkerFactory
Config — 配置管理
Config.php 递归扫描 config/ 目录,按目录层级嵌套合并(config/server.php → server.*)。支持:
- 编译缓存(
runtime/cache/config.php,buildCache()/isCached()) - 点分取值(
config('app.debug')),全量加载到内存后直接 dot-key 查找 - 保留目录跳过:
process/(进程发现)、command/(命令发现)、routes/(路由发现)不进入 Config 顶层键,由专用发现器独立扫描(参见Config::RESERVED_DIRS)
编译缓存限制:
buildCache()通过filterCacheable()递归过滤所有object类型值(包括Closure),因为缓存使用var_export序列化为 PHP 数组。如需延迟求值,请在运行时通过 Provider 绑定而非配置文件实现。
ProviderInterface — 服务提供者契约
ProviderInterface.php 采用两阶段生命周期:
register()— 仅容器绑定(所有 register 先于任何 boot 执行)boot($worker)— 可访问其他服务(路由、事件、探活等)
通过 bootMeta() 声明调度元数据:
critical:核心基础设施,boot 失败终止 Worker 启动network:涉及网络操作,启用pcntl_alarm超时保护timeout:建议超时秒数(null 沿用全局BootGuard::PROBE_TIMEOUT)
可选静态方法 bootAfter(): array 声明 boot 依赖,由 Sorter 拓扑排序。
PackageManifest — 包发现
PackageManifest.php 统一发现各子包通过 Install 类上的 #[Package] Attribute 声明的扩展点:
middleware/commands/providers/aliases- 发现来源:
vendor/composer/installed.json中各包extra.fiberphp.install声明(O(包数) 精准查找,非全量 PSR-4 扫描) - 缓存于
runtime/cache/packages.php,损坏时自动重建 - 重建命令:
php start.php package:discover
配置文件拷贝由 PackageInstaller 承担(读取 pathRelation,内部 installPaths/uninstallPaths 实现)。
优先级:config('providers') > PackageManifest::providers()。
Handler — 统一异常处理基类
Handler.php 覆盖 http / console / rpc 三种调用上下文的异常渲染与上报,子包/应用层可继承扩展(如 fiberphp/http 的 Handler 子类化返回 Response 对象)。
三个对外入口(final,禁止子类破坏调用契约):
handle($e, $context, $payload)— report + render 一步完成(最常用)report($e, $context)— 按shouldReport()(dontReport白名单)决定是否记录日志render($e, $context, $payload)— 按上下文分发到renderHttp/renderConsole/renderRpc/renderGeneric,内部异常降级为错误数组返回,永不抛出
静态工厂 resolve() 按约定解析 Handler 实例:App\ExceptionHandler(子类优先,兼容 Webman 旧约定)→ 兜底 self::class。debug 模式控制渲染详细程度(debug=true 时携带 file/line/trace)。
Pipeline — 协程感知管道
Pipeline.php 将中间件数组按洋葱模型组装为可缓存闭包,支持协程挂起/恢复:
build($pipes, $destination, $catch?)— 构建闭包(可缓存),同步和协程上下文均可用run($pipes, $destination, $passable, $catch?)— 在独立 Fiber 中执行管道,返回已启动的 Fiber
// 协程模式:中间件内 Fiber::suspend() 让出控制权
$fiber = Pipeline::run($middlewares, $handler, $request);
if ($fiber->isTerminated()) {
$response = $fiber->getReturn(); // 同步完成
} else {
$response = $fiber->resume($asyncData); // 中间件挂起,异步操作完成后恢复
}
中间件内可通过 Fiber::suspend() 挂起管道执行(如等待异步 I/O),事件循环 resume() 后继续。管道数组第一个元素为最外层(最先 before、最后 after)。
启动流程
以 App::run()(生产模式)为例,整体分为主进程引导与Worker 引导两阶段:
start.php
│ define BASE_PATH
│ require vendor/autoload.php
└─ App::run()
│
├─ Kernel::bootstrapMaster() # ===== 主进程引导(fork 前,执行一次)=====
│ ├─ enableErrors() # display_errors = on
│ ├─ registerMasterErrors() # master 阶段 set_error_handler + shutdown 兜底
│ ├─ loadEnv() # Env::load(.env) + Config::load()(需 BASE_PATH)
│ ├─ setRuntime() # timezone + error_reporting(读 app.* 配置)
│ └─ ensureLogDir() # 确保 runtime/logs 存在
│
├─ App::configureWorker(config('server')) # 写入 Worker 静态属性(pidFile/logFile...),事件循环固定为 Fiber
│
├─ loadProcess() # 扫描 config/process/*.php,重名检测
│
├─ foreach: WorkerFactory::start($name, $config) # 立即创建 Worker + 绑 onWorkerStart
│
└─ Worker::runAll() # 阻塞,进入事件循环 → fork N workers
└─ 每个 onWorkerStart 触发:
├─ Kernel::bootstrapWorker($worker) # ===== Worker 引导(fork 后,每进程一次)=====
│ ├─ registerErrors() # error→ErrorException + shutdown 防闪退
│ ├─ loadConfig() # Config::clear + reload,Container::reset
│ ├─ registerAliases() # PackageManifest aliases 绑定到 Container
│ ├─ loadFiles() # include config('autoload.files')
│ └─ bootProviders($worker, false)
│ ├─ gatherProviders() # 合并 config + PackageManifest,拓扑排序
│ ├─ 阶段1:逐个 register() # 容器绑定(失败则跳过该 Provider)
│ └─ 阶段2:逐个 boot() # BootGuard 按 bootMeta 决定超时/降级
│
└─ WorkerFactory::attachHandler() # 实例化 handler,绑定 onMessage 等回调
启动时序图
下图展示主进程与 Worker 子进程的交互时序,fork 边界将流程划分为「主进程引导」与「Worker 引导」两阶段,并包含运行时主从信号交互:
sequenceDiagram
autonumber
participant Master as 主进程
participant App as App
participant Kernel as Kernel
participant Factory as WorkerFactory
participant WM as Workerman
participant Worker as Worker 子进程
Note over Master,WM: ━━━ 阶段一:主进程引导(fork 前,执行一次) ━━━
Master->>App: App::run()
activate App
App->>Kernel: bootstrapMaster()
activate Kernel
Note right of Kernel: ① enableErrors<br/>② registerMasterErrors(set_error_handler + shutdown)<br/>③ loadEnv(Env + Config)<br/>④ setRuntime(时区 / 报错)<br/>⑤ ensureLogDir
deactivate Kernel
App->>App: configureWorker(config('server'))<br/>写入 Worker 静态属性(pidFile/logFile...),事件循环固定 Fiber
App->>App: loadProcess()<br/>扫描 config/process/*.php,重名检测
App->>Factory: WorkerFactory::start(name, config)
activate Factory
loop 每个进程配置
Factory->>WM: new Worker(listen, context)
Factory->>WM: 设置 count / name / reusePort 等属性
Factory->>WM: 绑定 onWorkerStart 回调(暂不执行)
end
deactivate Factory
deactivate App
App->>WM: Worker::runAll()
Note over Master,Worker: ══════ fork 边界 ══════<br/>Workerman 按 Worker->count 派生子进程<br/>主进程进入监控循环
WM->>Worker: fork 子进程(×count)
activate Worker
Note over Worker: ━━━ 阶段二:Worker 引导(fork 后,每进程一次) ━━━
Worker->>Kernel: onWorkerStart 触发 → bootstrapWorker($worker)
activate Kernel
Note right of Kernel: ① registerErrors(error→Exception + shutdown)<br/>② loadConfig(Config::clear + reload,Container::reset)<br/>③ registerAliases(PackageManifest aliases → Container)<br/>④ loadFiles<br/>⑤ bootProviders
Kernel->>Kernel: gatherProviders()<br/>Sorter::merge(config + Manifest) + 拓扑排序
rect rgb(255, 248, 240)
Kernel->>Kernel: 阶段1:逐个 Provider::register()(容器绑定)
Kernel->>Kernel: 阶段2:逐个 Provider::boot()<br/>BootGuard::safeBoot(超时保护 + 降级)
end
deactivate Kernel
Worker->>Factory: attachHandler($worker, $config)
activate Factory
Factory->>Factory: 实例化 handler(Container::make)
Factory->>Worker: 绑定 onMessage / onConnect / onClose ...
deactivate Factory
Note over Worker: ━━━ 阶段三:请求处理(进入事件循环) ━━━
Worker->>Worker: 处理 onMessage / onConnect / onClose
Note over Master,Worker: ━━━ 运行时主从信号交互 ━━━
Master-->>WM: reload 信号
WM-->>Worker: 触发 onWorkerReload(opcache_reset + 平滑重启)
Master-->>WM: stop 信号
WM-->>Worker: 优雅停止(stop_timeout=2s)
deactivate Worker
Provider boot 调度细节
BootGuard 对每个 Provider 的 boot 阶段:
resolveMeta()合并bootMeta()与全局BootGuard::PROBE_TIMEOUT- 若
network=true且有timeout:pcntl_alarm包裹boot()(双层超时,底层 socket 超时做亚秒级控制) - 异常处理:
FiberPHP\Exception\Exception走renderForBoot()输出结构化信息critical=true:重新抛出,终止 Worker 启动- 非 critical:记录 warning,降级继续
拓扑排序
Sorter 排序策略(优先级从高到低):
bootAfter()声明的依赖关系 → Kahn 算法拓扑排序app.boot_order作为同层级 tiebreaker(数字越小越早执行)- 未声明的保持发现顺序;存在环时追加到末尾并记录 warning
运行模式
入口示例(start.php):
#!/usr/bin/env php
<?php
use FiberPHP\App;
const BASE_PATH = __DIR__;
require_once __DIR__ . '/vendor/autoload.php';
App::run();
- 生产启动:
php start.php start - 后台运行:
php start.php start -d - 平滑重启:
php start.php reload - 停止:
php start.php stop
Console 场景调用 Kernel::bootstrapForConsole()(等价 bootstrapWorker(null, true)),只执行 register 阶段,跳过 boot 副作用。
配置说明
app.php
return [
'debug' => env('APP_DEBUG', false),
'name' => env('APP_NAME', 'fiberphp'),
'boot_order' => [], // [Provider 类名 => 优先级],数字越小越早执行(拓扑排序的同层级 tiebreaker)
// master 阶段 bootstrap 列表(fork 前执行一次);留空数组(默认)使用 Kernel 内置顺序,非空数组则整体覆盖
'master_bootstrap' => [],
// worker 阶段 bootstrap 列表(fork 后每进程执行一次);语义同上
'worker_bootstrap' => [],
];
boot 阶段策略:
strict固定为 true(critical Provider 失败即终止);探活超时固定为BootGuard::PROBE_TIMEOUT(3 秒),均不可配置。
server.php(应用层)
控制 Workerman 全局属性:pid_file / stdout_file / log_file / status_file / max_package_size / stop_timeout。事件循环固定为 Workerman\Events\Fiber(基于 revolt/event-loop),由框架硬编码,不可配置。
应用接入
框架作为 Composer 库包发布,其 composer.json 仅含本地 test 脚本(composer test)——库包的 post-autoload-dump / pre-package-uninstall 等钩子不会在作为依赖安装时执行。应用方需在自己的 composer.json 中注册以下脚本,才能让 PackageInstaller 在依赖变更时自动完成配置拷贝与包发现清单重建:
{
"scripts": {
"post-autoload-dump": "FiberPHP\\PackageInstaller::discover",
"pre-package-uninstall": "FiberPHP\\PackageInstaller::uninstall"
}
}
post-autoload-dump:所有包安装/更新/卸载完成、autoload 重新生成后触发一次,统一发现并拷贝子包配置、重建PackageManifest清单pre-package-uninstall:包被卸载前触发,清理对应子包已拷贝的配置文件
包发现机制
- 子包在
composer.json的extra.fiberphp.install声明Install类全限定名;Install类通过#[Package]Attribute 声明pathRelation/middleware/commands/providers/aliases - Composer
post-autoload-dump触发 PackageInstaller::discover():读取vendor/composer/installed.json中所有extra.fiberphp.install声明,遍历对应 Install 类读取 Attribute 的pathRelation经 PackageInstaller 拷贝配置,再PackageManifest::build()重建清单 - 卸载时
pre-package-uninstall触发PackageInstaller::uninstall(),从被卸载包的extra.fiberphp.install读取 Install 类,经PackageInstaller清理配置文件 - Worker 启动时
Kernel::gatherProviders()合并config('providers')与PackageManifest::providers()
声明示例:
use FiberPHP\Attribute\Package;
#[Package(
pathRelation: ['config/mysql.php' => 'config/mysql.php'],
providers: [DbProvider::class],
commands: [SomeCommand::class],
middleware: [SomeMiddleware::class],
aliases: ['MyFacade' => MyClass::class],
)]
class Install {}
全局函数
定义于 helpers.php:
| 函数 | 说明 |
|---|---|
base_path() / app_path() / config_path() / route_path() / runtime_path() / public_path() | 路径助手 |
config($key, $default) | 读取配置 |
app($abstract, $constructor) | 获取容器或解析依赖 |
container() | 获取 Container 单例 |
env($key, $default) / env_int($key, $default) | 读取环境变量(字符串/整型) |
logger() | 获取 LoggerInterface 实例(兜底为框架自带 Logger) |
copy_dir() / remove_dir() / get_realpath() / cpu_count() | 文件/系统助手 |
命名冲突防护: 以上函数均通过
if (!function_exists(...))保护性定义,若用户项目已定义同名函数则框架版本不会被加载。但请注意,以下函数被框架核心代码直接调用,自定义时需保持兼容的签名与返回类型:path_combine、base_path、app_path、config_path、route_path、runtime_path、public_path、config、env、env_int、copy_dir、remove_dir、get_realpath、cpu_count、app、container、logger
子包扩展
子包按发布进度逐步更新,已发布的子包列表见 Packagist。