FrankenPHP 默认不支持 PHP 文件热重载,因其由 Caddy 主导进程生命周期,PHP worker 无法被外部信号中断重载;--watch 参数在 octane:start --server=frankenphp 中被忽略,需手动重启 Caddy 进程或改用 php_fastcgi + entr/watchexec 方案。

FrankenPHP 默认不支持 PHP 文件热重载
FrankenPHP 本身是基于 Caddy 的 SAPI 运行时,它没有内置类似 Laravel Mix 或 Symfony CLI 那样的文件监听 + 自动重启机制。所谓“Octane 热重载”,实际是 php artisan octane:start 在传统 Swoole/ReactPHP 下借助 --watch 参数触发的进程重启——但这个参数在 FrankenPHP 驱动下被忽略,因为 FrankenPHP 不走 Octane 的 worker 生命周期管理逻辑。
octane:start --server=frankenphp 时 --watch 无效
运行命令后你会看到控制台输出明确提示:Warning: The --watch option is not supported when using the frankenphp server. 这不是警告级别问题,而是架构限制:FrankenPHP 由 Caddy 主导进程生命周期,PHP worker 是被动加载的,无法被外部进程信号中断并重载。
- FrankenPHP 的 PHP 实例是按需启动(per-request)或长驻(via
frankenphp.workers),不提供kill + fork接口供 Octane 监听文件变更 -
--watch依赖inotify(Linux)或fsevents(macOS)监听文件变化,再调用exec()重启 worker,但 FrankenPHP 拒绝这种接管 - 即使你手动改了
.env或config/app.php,FrankenPHP worker 也不会自动 reload,必须手动重启 Caddy 进程
替代方案:用 Caddy 的 file_server + php_fastcgi 模式配合 systemd 或 entr
如果你真需要开发时接近“热重载”的体验,得绕过 FrankenPHP 的纯模式,退回到 FastCGI 模式,并自己搭监听链路:
- 把 Caddyfile 中的
frankenphp块换成php_fastcgi unix//run/php/php-fpm.sock(确保 php-fpm 启动) - 用
entr监听 PHP 文件变更:find app config routes database lang -name "*.php" | entr -r sh -c "sudo systemctl reload php-fpm"
- 或者用
watchexec(更现代):watchexec -e php --on-change "sudo systemctl reload php-fpm" --recursive app/ config/ routes/
- 注意:FPM reload 会中断正在处理的请求,不适合生产,但开发阶段可接受;且
.env变更仍需重启 FPM(因被读入内存)
FrankenPHP 开发期真实可行的最小刷新策略
别强求“热重载”,FrankenPHP 的设计哲学是轻量、安全、贴近 HTTP/3 原语。开发时最务实的做法是:
立即学习“PHP免费学习笔记(深入)”;
- 保持
frankenphp模式不变,只在 Caddyfile 里加debug日志,用caddy fmt和caddy validate快速校验配置 - PHP 代码改完后,执行
sudo systemctl restart caddy—— 实测冷启动通常 - 如果用 Docker,把
/var/www/html绑定挂载,配合docker compose restart app更可控 - 环境变量更新必须重建容器或重载 Caddy,
.env不会被 FrankenPHP runtime 动态读取
真正卡点不在“怎么热”,而在接受 FrankenPHP 的边界:它不模拟传统 PHP 生命周期,也不假装自己是 Octane 的另一个 driver。想热,就得换角色——要么切回 FPM+entr,要么接受 systemctl restart caddy 就是你的 reload 键。



















