hyperf 废除 $_get、$_post 等全局变量是强制要求,因常驻内存下协程共享进程内存,使用会导致跨协程数据污染和安全漏洞;必须通过 di 注入 requestinterface 实例,调用 input()、json()、file() 等方法获取隔离的请求数据。

Hyperf 中不能用 $_GET、$_POST、$_SERVER 等全局变量,必须通过 RequestInterface 实例获取请求数据。 这不是约定,而是强制要求——因为常驻内存模型下,全局变量会跨协程污染,直接导致用户数据错乱或安全漏洞。
为什么 $_GET 在 Hyperf 里根本不可用
Hyperf 基于 Swoole 协程运行,所有请求共享同一进程内存。如果允许 $_GET,协程 A 和 B 同时执行时,$_GET['id'] 可能被反复覆盖。比如:
- 协程 A 设置
$_GET = ['id' => '1001'] - CPU 切到协程 B,它把
$_GET改成['id' => '1002'] - A 恢复执行,读到的却是
'1002'——张三看到李四的数据
Hyperf 废除所有 PHP-FPM 风格的超全局变量,是线程/协程安全的硬性保障,不是“建议不使用”。
如何正确注入 RequestInterface 获取查询参数
Hyperf 通过 DI 容器自动解析 ServerRequestInterface 或其兼容接口(如 RequestInterface),你只需声明类型提示即可。以下方式都有效:
- 在 Controller 方法参数中直接写:
public function index(RequestInterface $request) - 在构造函数中注入:
public function __construct(private RequestInterface $request) - 用
@Inject注解注入属性(需protected或public):/** @Inject */ protected RequestInterface $request;
获取查询参数统一用 $request->input('key', 'default'),它自动合并 GET 和 POST 数据,无需区分来源。
RequestInterface 和 ServerRequestInterface 的区别与选型
Hyperf 的 RequestInterface 是对 PSR-7 ServerRequestInterface 的轻量封装,二者在绝大多数场景可互换。但注意:
-
ServerRequestInterface是标准接口,更通用,适合需要严格遵循 PSR 规范的模块 -
RequestInterface是 Hyperf 自定义接口,额外提供了input()、all()、file()等便捷方法,开发效率更高 - DI 容器默认绑定的是
Hyperf\HttpServer\Contract\RequestInterface,直接依赖它更稳妥 - 若手动调用
Context::get(ServerRequestInterface::class),需确保中间件已存入上下文(通常已自动完成)
常见踩坑点:路径参数、JSON Body、文件上传怎么取
别试图从 $_GET 或 $_FILES 找数据,全走 $request:
- 路径参数(如
/user/{id}):直接声明方法参数类型,如public function show(int $id),Hyperf 自动解析并类型转换 - JSON 请求体:用
$request->json()->get('field')或$request->all()(自动解析 body) - 上传文件:用
$request->file('avatar'),返回UploadedFileInterface实例 - 原始 server 参数(如 remote IP):用
$request->server('remote_addr'),而非$_SERVER['REMOTE_ADDR']
所有这些操作都基于当前协程上下文隔离的对象,不存在并发干扰。真正的难点不在“怎么写”,而在于彻底放弃“我以前在 Laravel/ThinkPHP 里就是这么写的”这种惯性思维——Hyperf 的请求对象不是替代品,它是唯一合法入口。











