ThinkPHP 6.1 本身不内置 WebSocket 服务,必须依赖 Swoole 扩展(≥4.8.0)和 think-swoole 包;php-fpm 无法处理 WebSocket 握手,必须用 php think swoole 启动常驻进程,并正确配置 swoole.php 启用 WebSocket、指定 handler 与路由文件。

直接上结论:ThinkPHP 6.1 本身不内置 WebSocket 服务,必须依赖 swoole 扩展 + topthink/think-swoole 包才能启用;用 php-fpm 启动的 HTTP 服务完全无法响应 WebSocket 握手请求——这点最容易被忽略,也是 90% 连接失败的根源。
确认 swoole 扩展已正确加载且版本兼容
ThinkPHP 6.1 要求 swoole ≥ 4.8.0(推荐 4.10+),低于该版本可能触发 Class Swoole\WebSocket\Server not found 或握手后立即断开。
- 执行
php -m | grep swoole,有输出才表示扩展已加载;若无,需检查php.ini是否含extension=swoole并重启 PHP 服务 - 运行
php --ri swoole查看版本,若为 4.7.x 或更低,建议升级:pecl install swoole-4.10.0 - 注意:Windows 下官方不支持 Swoole 扩展,开发环境务必用 Linux/macOS 或 WSL
安装 think-swoole 并配置 swoole.php
仅装扩展还不够,think-swoole 是 ThinkPHP 官方封装的 Swoole 集成层,它接管了 WebSocket 生命周期和事件路由。
- 执行
composer require topthink/think-swoole(6.1 兼容^3.0版本) - 修改
config/swoole.php,关键项必须显式设置:-
'websocket' => ['enabled' => true]—— 不设为true,服务启动后根本不监听Upgrade请求 -
'handler' => \app\listener\WsHandler::class—— 该类必须存在且实现onOpen/onMessage/onClose -
'route_file' => app_path() . 'websocket.php'—— 路由文件路径必须绝对,不能用相对路径或字符串拼接错误
-
- 若 config/swoole.php 不存在,运行
php think swoole:publish生成默认配置
定义路由文件 websocket.php 并实现事件处理器
ThinkPHP 6.1 的 WebSocket 路由不走 HTTP 控制器,而是通过 websocket.php 映射消息类型到具体方法,否则 onMessage 收到数据却无法分发。
立即学习“PHP免费学习笔记(深入)”;
- 在
app/目录下新建websocket.php,内容至少包含:return [ 'ping' => [\app\listener\WsHandler::class, 'onPing'], 'chat' => [\app\listener\WsHandler::class, 'onChat'], ]; -
app\listener\WsHandler类须继承think\swoole\websocket\WebSocket,不能只写普通类;否则onOpen中的$server->push()会报错 - 注意:该类中的
onMessage方法接收的是原始Swoole\WebSocket\Frame对象,不是 ThinkPHP 的 Request 对象,别试图调$request->post()
Nginx 反向代理 wss 必须传 Upgrade 头
本地 ws://localhost:9501 能连 ≠ 线上 wss://your.com/ws 能连;Nginx 缺少关键 header 会导致 400 或连接后秒断。
- 在站点配置中添加 location 块(不是全局 http 块):
location /ws { proxy_pass http://127.0.0.1:9501; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 86400; } - 前端连接地址必须与 Nginx
location路径一致:new WebSocket("wss://your.com/ws"),多一个斜杠或少一个都失败 - SSL 证书必须有效且域名匹配,浏览器对
wss的证书校验比https更严格,自签名证书必拒
最常被跳过的一步:启动命令不是 php think serve,而是 php think swoole;服务起来后,端口(默认 9501)必须在服务器防火墙放行,且不能被宝塔或其他进程占用。一旦看到 WebSocket server started on 0.0.0.0:9501,才真正进入可测试阶段。



















