本质是FrankenPHP以常驻worker模式运行,代码仅加载一次;需通过文件监听+USR2信号重启+禁用opcache三环节协同实现热重载。

FrankenPHP 本地开发时代码修改不生效,本质不是 FrankenPHP “不支持热重载”,而是它默认以高性能常驻模式运行——PHP 代码只加载一次,后续请求复用内存中的字节码。要实现修改即刷新,必须主动引入监听 + 重启机制。关键不在改 FrankenPHP 本身,而在补全开发链路的三个环节:文件变更能被感知、变更后能触发服务重启、重启逻辑与 FrankenPHP 的 worker 模式兼容。
确认是否启用 worker 模式
FrankenPHP 的热重载只在 worker 模式下可有效配合外部工具实现。普通 Caddy + php_server 模式是纯 HTTP 转发,不持有 PHP 进程,无法 reload。
- 检查入口脚本(如
frankenphp-worker.php)是否被正确调用,且内容包含frankenphp_handle_request()循环 - 启动命令应为:
frankenphp run --worker或通过 Laravel Octane 启动:php artisan octane:start --server=frankenphp - 若用
frankenphp run(无 --worker),它等价于静态文件服务器,改代码自然不生效
用 hyperf/watcher 或自定义 inotify 监控并发送 USR2
FrankenPHP 的 worker 进程支持 SIGUSR2 信号触发平滑重启,这是热重载的核心通路。
- 推荐安装
@hyperf/watcher(轻量、稳定、跨平台):composer require hyperf/watcher --dev
然后执行:php vendor/bin/watcher watch - 手动方案(Linux/macOS):用
fswatch或inotifywait监听app/和config/目录,变更时执行:kill -USR2 $(cat runtime/frankenphp.pid)(确保 pid 文件路径与实际一致) - 注意:FrankenPHP 默认把主进程 PID 写入
runtime/frankenphp.pid,若你改过--pidfile参数,需同步调整脚本
避免 opcache 和类加载缓存干扰
即使重启了 worker,如果 PHP 缓存没清,新代码仍可能不加载。
立即学习“PHP免费学习笔记(深入)”;
- 开发环境务必禁用 opcache:
在php.ini中设opcache.enable=0,或通过环境变量OPCACHE_ENABLE=0注入容器 - Composer 自动加载需关闭权威模式:
在composer.json的"autoload"下添加:"classmap-authoritative": false,并运行composer dump-autoload - 不要依赖
opcache_invalidate()或apcu_clear_cache()—— worker 重启后整个 PHP 实例已重建,这些函数无效
验证与调试要点
常见“不生效”其实是配置错位,而非 FrankenPHP 问题。
- 确认
APP_DEBUG=true且未启用守护模式(-d);php artisan octane:start -d后octane:reload会失败 - 检查
runtime/目录权限,确保 FrankenPHP 能写入frankenphp.pid - 用
ps aux | grep frankenphp确认只有一个主进程(PID 1),多个 worker 是正常的;若看到多个主进程,说明监控脚本重复触发了启动 - 临时加日志到 worker 入口:在
frankenphp-worker.php开头写file_put_contents('/tmp/start.log', date('Y-m-d H:i:s') . "\n", FILE_APPEND);,看每次修改后是否生成新时间戳



















