fiberphp/framework

FiberPHP framework core: application lifecycle orchestration, config management, service providers, package discovery.

Maintainers

Package info

gitee.com/FiberPHP/framework.git

Issues

pkg:composer/fiberphp/framework

Transparency log

Statistics

Installs: 12

Dependents: 8

Suggesters: 0

v0.1.0 2026-08-22 04:32 UTC
No longer found in upstream repository

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.1fiberphp/container dev-masterpsr/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 是单例,纯编排职责:"在正确的时机调用正确的步骤"。职责被拆解到独立类:

Config — 配置管理

Config.php 递归扫描 config/ 目录,按目录层级嵌套合并(config/server.phpserver.*)。支持:

  • 编译缓存(runtime/cache/config.phpbuildCache() / isCached()
  • 点分取值(config('app.debug')),全量加载到内存后直接 dot-key 查找
  • 保留目录跳过:process/(进程发现)、command/(命令发现)、routes/(路由发现)不进入 Config 顶层键,由专用发现器独立扫描(参见 Config::RESERVED_DIRS

编译缓存限制: buildCache() 通过 filterCacheable() 递归过滤所有 object 类型值(包括 Closure),因为缓存使用 var_export 序列化为 PHP 数组。如需延迟求值,请在运行时通过 Provider 绑定而非配置文件实现。

ProviderInterface — 服务提供者契约

ProviderInterface.php 采用两阶段生命周期:

  1. register() — 仅容器绑定(所有 register 先于任何 boot 执行)
  2. 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/httpHandler 子类化返回 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::classdebug 模式控制渲染详细程度(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 阶段:

  1. resolveMeta() 合并 bootMeta() 与全局 BootGuard::PROBE_TIMEOUT
  2. network=true 且有 timeoutpcntl_alarm 包裹 boot()(双层超时,底层 socket 超时做亚秒级控制)
  3. 异常处理:
    • FiberPHP\Exception\ExceptionrenderForBoot() 输出结构化信息
    • critical=true:重新抛出,终止 Worker 启动
    • 非 critical:记录 warning,降级继续

拓扑排序

Sorter 排序策略(优先级从高到低):

  1. bootAfter() 声明的依赖关系 → Kahn 算法拓扑排序
  2. app.boot_order 作为同层级 tiebreaker(数字越小越早执行)
  3. 未声明的保持发现顺序;存在环时追加到末尾并记录 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:包被卸载前触发,清理对应子包已拷贝的配置文件

包发现机制

  1. 子包在 composer.jsonextra.fiberphp.install 声明 Install 类全限定名;Install 类通过 #[Package] Attribute 声明 pathRelation / middleware / commands / providers / aliases
  2. Composer post-autoload-dump 触发 PackageInstaller::discover():读取 vendor/composer/installed.json 中所有 extra.fiberphp.install 声明,遍历对应 Install 类读取 Attribute 的 pathRelationPackageInstaller 拷贝配置,再 PackageManifest::build() 重建清单
  3. 卸载时 pre-package-uninstall 触发 PackageInstaller::uninstall(),从被卸载包的 extra.fiberphp.install 读取 Install 类,经 PackageInstaller 清理配置文件
  4. 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_combinebase_pathapp_pathconfig_pathroute_pathruntime_pathpublic_pathconfigenvenv_intcopy_dirremove_dirget_realpathcpu_countappcontainerlogger

子包扩展

子包按发布进度逐步更新,已发布的子包列表见 Packagist。