本项目是基于 TypePHP(将 PHP 代码静态 AOT 编译为 C++ 原生机器码)对 Webman / Workerman 进行独立二进制程序编译、打包与运行的实践方案。
build.bat调用
tpc.exe project.yml,通过 MSVCcl.exe+link.exe编译生成build/webman_server.exe。
package.bat先执行
build.bat,随后将可执行文件、核心动态库 DLL、PHP 扩展(ext)、配置文件与视图模板等自动同步打包至dist/目录。
# 方式 1:进入 dist 目录直接启动二进制
cd dist
.\webman-server.exe
# 方式 2:执行启动脚本(自动配置 PHPRC 与 PATH)
.\dist\run.batLinux release packages provide the same self-contained entry point:
cd dist
./webman-server startThe webman-server launcher sets PHPRC and the local library path before
executing the compiled webman-server.bin, so the adjacent php.ini is used
even when the binary is started directly.
- PHP_HOME 环境变量指向错误
- 现象:构建时找不到
php8ts.lib/phpx.lib,或 DLL 缺失导致链接失败。 - 解决:在
build.bat和package.bat中强制显式指定set "PHP_HOME=D:\workspace\tpc_v0.6.5_windows_x86_64",不再依赖可能冲突的系统环境变量。
- 现象:构建时找不到
- Windows CMD 字符编码冲突
- 现象:批处理文件在 Windows 默认 GBK 终端下因 UTF-8 中文注释乱码直接中断退出。
- 解决:脚本统一使用标准英文日志与 ASCII 编码注释。
- 工作目录 (CWD) 与动态库加载路径问题
- 现象:在项目根目录下直接运行
.\dist\webman-server.exe报错找不到配置或 DLL。 - 解决:在
run.bat中通过cd /d "%~dp0"切入dist/,并设置PHPRC与PATH。
- 现象:在项目根目录下直接运行
- 重复类/函数定义冲突 (Duplicate class / Cannot redeclare function)
- 现象:
support\Request、FastRoutesimpleDispatcher()等提示重复定义。 - 解决:在
project.yml中忽略根目录冗余的support,只保留vendor/workerman/webman-framework/src/support;在main.php中移除动态require_once $autoload;,由 TypePHP 统一进行静态符号管理。
- 现象:
- 不支持动态语言特性
extract()与$$语法- 现象:
Raw.php模板引擎编译时报Unsupported function: extract或The $$ syntax is not supported。 - 原因:C++ 强类型静态编译器无法在编译期为动态变量注入确定栈帧。
- 解决:重构
Raw.php的模板变量渲染逻辑,采用静态友好的内容占位替换方案。
- 现象:
- SAPI 运行模式拦截 (
checkSapiEnv)- 现象:Workerman 抛出异常强制退出,因为当前运行在
embedSAPI(内嵌 PHP 运行时)下。 - 解决:修改
Worker.php的checkSapiEnv(),允许PHP_SAPI === 'embed'。
- 现象:Workerman 抛出异常强制退出,因为当前运行在
- 无参闭包传参严格报错 (
ArgumentCountError)- 现象:
set_error_handler(static fn (): bool => true)与Worker::stopAll()的array_walk抛出expects exactly 0 arguments, 4 given。 - 解决:将所有错误处理闭包声明为变长参数
static fn (...$args): bool => true。
- 现象:
- Windows 下回调方法的访问控制权限错误 (
TypeError)- 现象:外部事件循环与注册的 shutdown 函数调用
checkErrors()、acceptTcpConnection()、acceptUdpConnection()时报cannot access protected method。 - 解决:将这些跨上下文调用的类方法访问级别从
protected改为public。
- 现象:外部事件循环与注册的 shutdown 函数调用
- 命名空间与别名歧义导致的方法未定义 (
Invalid callback)- 现象:
support\App::request、Webman\Route\Route::dispatch、Webman\Route\Route::getFallback等方法不存在报错。 - 原因:类中同时
use了属性注解同名类(如RouteAttribute、MiddlewareAttribute),AOT 编译器在 AST 解析时发生歧义绑定。 - 解决:在关键分发逻辑中显式指定全限定类名(如
\Webman\Route::dispatch()、\Webman\App::request()等)。
- 现象:
- 单机模式缺少 Route/Middleware 启动装载
- 现象:
call method dispatch on null。 - 解决:在
main.php启动序列中主动调用\Webman\Middleware::load()与\Webman\Route::load([config_path()])。
- 现象:
以下修改点可向官方仓库提交 PR,有助于提升框架在 PHP 8 严格模式、静态分析工具以及原生嵌入式(SAPI/AOT)环境下的兼容性。
PR 标题:fix: improve PHP 8 strict callback compatibility, visibility, and allow embed SAPI
修改内容说明:
- 统一错误处理器与退出回调形参签名(修复
ArgumentCountError):- 将
Worker.php中的set_error_handler(static fn (): bool => true)调整为set_error_handler(static fn (...$args): bool => true)。 - 将
Worker::stopAll()中array_walk的闭包形参调整为static fn (Worker $worker, mixed ...$args) => $worker->stop(false)。
- 将
- 支持
embedSAPI 运行环境:- 在
Worker::checkSapiEnv()中补充支持PHP_SAPI === 'embed'。
- 在
- 修复网络接收、错误检查与信号处理回调的访问控制及类型兼容(修复
TypeError):- 将
Worker类中的acceptTcpConnection()、acceptUdpConnection()、checkErrors()与signalHandler()访问修饰符由protected调整为public,确保在 Event 扩展或全局生命周期中作为callable回调时具备正确的访问权限。 - 使用现代
static::signalHandler(...)第一型可调用语法注册信号。
- 将
PR 标题:fix: eliminate Route/Middleware attribute alias ambiguity and fix getFallback signature
修改内容说明:
- 消除属性注解与核心类同名引起的符号歧义:
- 在
App.php中使用\Webman\Route::dispatch()与\Webman\Route::getFallback(),避免与局部引入的Webman\Route\Route as RouteObject/support\annotation\route\Route发生 AST 解析二义性。 - 在
Route.php中使用static::setCollector()替代Route::setCollector()。
- 在
- 规范默认 404 回调签名:
- 将
App::getFallback()默认返回的闭包形参规范为function ($req = null),防止分发器传参时在严格参数校验模式下抛出参数个数不匹配异常。
- 将
- 优化
Middleware::prepareAttributeMiddlewares传参:- 避免将临时数组直接作为引用传递,提升类型安全性。