必须用workerman 5.0而非4.x,因其基于revolt/event-loop原生支持await语法,允许在onmessage中同步写法实现异步执行;4.x仅支持回调式异步,无法使用await且会静默降级。

PHP 8.1+(包括最新 8.3/8.4)用 Workerman 实现异步,**不需要 Swoole、不需要额外扩展、不改 php.ini**,但必须用 workerman/workerman:^5.0 —— 低版本(如 4.x)在 PHP 8.2+ 上已无法启用协程,且会静默降级为纯异步回调模式,根本不是你想要的“同步写法 + 异步执行”。
为什么必须用 Workerman 5.0 而不是 4.x
Workerman 4.x 的事件循环基于 stream_select 或 libevent,它只支持「回调式异步」,所有网络 I/O(HTTP 请求、MySQL 查询、Redis 调用)都得手动拆成 onConnect/onMessage 链式调用,逻辑分散、易出错、调试困难。而 5.0 重构为基于 revolt/event-loop,原生支持 await 语法,允许你在 onMessage 里直接写:
$response = await $client->get('https://api.example.com');
$body = await $response->getBody();
——这行代码不会阻塞其他连接,但写法和同步完全一致。4.x 做不到这点,强行用 await 会报 Fatal error: Uncaught Error: Call to undefined function co::sleep() 或直接忽略 await 变成同步阻塞。
导入协程运行时的三步硬要求
Workerman 5.0 的协程能力不是“开箱即用”,必须显式激活,漏掉任意一步都会退化为普通异步(无 await 支持):
- 安装时必须指定
^5.0:运行composer require workerman/workerman:^5.0,不能只写workerman/workerman(Composer 默认可能拉 4.x) - 启动脚本顶部必须引入 autoload 并触发协程初始化:
require_once __DIR__ . '/vendor/autoload.php';后**立刻**调用\Workerman\Worker::init();(官方文档常漏掉这句,但缺了就无协程) - PHP 进程必须以 CLI 模式运行,且不能启用
opcache.enable_cli=1(会干扰 Revolt 的协程调度),建议在php.ini中设为opcache.enable_cli=0
常见错误:await 不生效,或报 “Call to undefined function await”
这不是 PHP 版本问题,而是环境没对齐:
-
await是 Revolt 提供的语法糖,不是 PHP 内置关键字 —— 它依赖workerman/http-client或workerman/mysql等组件返回的Promise对象;直接对file_get_contents或curl_exec用await必然失败 - 确保用了协程兼容的客户端:HTTP 用
Workerman\Http\Client,MySQL 用Workerman\Mysql,Redis 用Workerman\Redis;混用mysqli或PDO会导致整个协程上下文卡死 - 检查是否误用了
sleep(1):必须换成await \Workerman\Timer::sleep(1),否则线程阻塞,协程调度器停摆
PHP 8.3+ 下的特殊注意点
PHP 8.3 引入了 #[\ReturnTypeWillChange] 属性自动注入机制,但 Revolt 的某些内部类(如 Revolt\EventLoop\Driver)尚未完全适配,可能触发 Deprecated: Return type of ... should include null 警告。这不是致命错误,但若开启 error_reporting(E_ALL) 会刷屏。解决方案是:
- 临时关闭严格警告:
error_reporting(E_ALL & ~E_DEPRECATED);(仅开发期) - 或升级到
revolt/event-loop:^1.1(Workerman 5.0.3+ 已内置该修复) - 切勿自行 patch Revolt 源码 —— Workerman 的事件循环封装层与 Revolt 版本强绑定,错配会导致
EventLoop is already running死锁
真正难的不是写 await,而是守住边界:所有 I/O 必须走协程客户端,所有延时必须用 Timer::sleep,所有第三方库(比如 Guzzle)必须替换。一旦混入一个阻塞调用,整个 worker 进程就卡住,连健康检查请求都收不到 —— 这个坑,90% 的人第一次上线就踩中。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











