FrankenPHP 默认启动 HTTP server 模式,Worker 模式必须显式启用:frankenphp start --worker /path/to/worker.php;该脚本需遵循协议——不输出响应头、不调用 exit/die、通过 frankenphp\events() 循环处理请求,并从 Request 对象获取参数,否则会崩溃或失效。

frankenphp start --worker 模式必须显式启用
FrankenPHP 默认启动的是 HTTP server 模式(即内置 Caddy 处理完整 HTTP 生命周期),Worker 模式不会自动开启。不加参数直接运行 frankenphp start,它只会跑一个常驻 PHP 进程处理单个请求流,不是你想要的“复用容器、热加载、长驻内存”的 Worker 行为。
要真正进入 Worker 模式,必须加 --worker 标志,并指定入口脚本:
frankenphp start --worker /path/to/worker.php- 这个
worker.php必须是符合 FrankenPHP Worker 协议的脚本:它不能输出 HTTP 响应头,不能调用exit()或die(),且需在顶层循环中持续监听frankenphp\events()或使用frankenphp\handle_request()显式处理每个请求 - 常见错误:把 Laravel 的
public/index.php直接当 Worker 脚本用 —— 它依赖完整 HTTP 环境和响应发送逻辑,会崩溃或卡死
Worker 脚本里不能用 $_SERVER['REQUEST_METHOD'] 这类超全局变量
Worker 模式下,PHP 不再通过 CGI/FPM 协议接收请求,而是由 FrankenPHP 的 Go 层以结构化数据推送过来。所有请求上下文都封装在 frankenphp\Request 对象里。
典型写法是:
立即学习“PHP免费学习笔记(深入)”;
<?php
use frankenphp\Request;
use frankenphp\Response;
while ($request = frankenphp\events()) {
if ($request instanceof Request) {
$response = new Response("Hello from worker", 200, ['Content-Type' => 'text/plain']);
frankenphp\respond($response);
}
}
容易踩的坑:
- 继续读取
$_GET、$_POST、$_COOKIE—— 它们为空或不准确,必须从$request->query()、$request->post()、$request->cookies()获取 - 试图调用
header()或http_response_code()—— 无效,必须构造Response对象并传给frankenphp\respond() - 在循环外提前
return或抛出未捕获异常 —— 整个 Worker 进程会退出,后续请求无处理者
打包产物里如何让 Worker 自动重启代码变更
FrankenPHP 的 Worker 模式支持热重载,但只对 --worker 启动时指定的脚本及其 require / include 的文件生效,不递归监听 vendor 或框架源码。
实操要点:
- 确保你的
worker.php是项目根目录下的单一入口,所有业务逻辑通过require引入,比如:require __DIR__ . '/app/worker_handler.php'; - 修改
worker_handler.php后,FrankenPHP 会在下一个请求前自动 reload 整个 Worker 进程(无需手动Ctrl+C) - 如果用了 Composer autoload,注意
vendor/autoload.php本身不会触发 reload —— 改动框架类或第三方包,得靠--watch配合自定义路径,例如:frankenphp start --worker worker.php --watch app/,config/ - 生产环境建议关掉
--watch,改用进程管理器(如 systemd)配合文件哈希校验 + 信号重启
frankenphp serve 和 frankenphp start --worker 的本质区别
很多人混淆这两个命令,以为只是写法不同。其实它们启动的是完全不同的执行模型:
-
frankenphp serve:启动 Caddy + PHP 的混合服务,走标准 HTTP 协议栈,适合传统 Web 页面、静态资源托管、HTTPS 终止等场景;所有请求仍走index.php入口,框架生命周期每次重建 -
frankenphp start --worker:启动纯 Worker 进程,Caddy 退化为反向代理(或干脆不用),PHP 进程常驻,仅复用 autoloader、DI 容器、数据库连接池等 —— 这才是性能提升的核心路径 - 二者不能混用:在
serve模式下加--worker参数会报错;反过来,在start --worker下配置 Caddyfile 的路由规则也无效,因为 Caddy 此时不接管 PHP 请求
Worker 模式真正的复杂点不在启动命令,而在于你写的那个 worker.php 是否真正理解了“一次加载、多次调用”的契约 —— 框架初始化代码放哪、连接要不要复用、全局状态怎么清理,这些细节没处理好,反而比 FPM 更容易出问题。



















