Hyperf JSON-RPC 参数丢失主因是 RequestDTO 字段名、访问修饰符(须 public)、类型声明三者未与请求 JSON key 严格一致,框架静默跳过不匹配字段且不报错。
Hyperf 的
调用中参数丢失,90% 以上不是网络或配置问题,而是
定义与实际传参结构不匹配导致的反序列化失败——框架静默丢弃字段,不报错也不警告。
为什么 DTO 字段会“消失”而不是报错
Hyperf 默认使用
解析请求体,再通过反射 + 属性赋值填充
实例。它只处理 public 属性或带
注解且有 setter 方法的属性;private/protected 属性、未声明类型、拼写不一致的 key 全部被跳过,且无日志提示。
中字段名必须与 JSON 请求中的 key 完全一致(区分大小写)
没有
访问修饰符,也没有对应
方法时,该字段不会被赋值
类型声明缺失(如
写成
)会导致类型推断失败,反序列化后为
数组嵌套结构需显式声明为
或具体对象数组,如
检查 RequestDTO 的三个关键点
以常见错误为例:前端传
,但服务端
定义如下:
确认字段命名:用
就写
,别依赖驼峰转换(Hyperf 默认不开启自动映射)
确认访问控制:必须是
,
或
一律忽略
确认类型注解:PHP 8.0+ 推荐用 PHP 原生类型(
,
),否则需补
,例如
如何快速验证 DTO 是否生效
在 RPC 方法入口加一行调试输出,绕过业务逻辑直接看原始数据:
php版微信js-sdk支付接口类
php版微信js-sdk支付接口类
下载
如果
里有
,但
里没有,说明 DTO 映射失败
如果两者都有
但值为
,检查字段是否为
且类型兼容(比如传字符串给
字段)
不要依赖 IDE 自动补全的 setter —— Hyperf 不调用它们,只靠属性直赋
Hyperf JsonRpc 的参数绑定不走 Laravel 风格的表单请求验证流程
很多人误以为加了
注解或继承
就能触发验证和字段映射,其实不能。Hyperf 的
参数绑定是独立于 HTTP 中间件链的,它由
实现,默认就是直解析 + 直赋值。
验证逻辑(如
)只在控制器层或手动调用
时生效,不影响 DTO 构造
想强制校验字段存在性,得在 DTO 中加
并抛异常,或改用
+ 手动解析(不推荐,破坏 RPC 语义)
真正可靠的方案是:DTO 字段名、类型、可见性三者严格对齐请求体结构,不依赖任何“自动转换”机制
最易被忽略的是字段命名一致性——Hyperf 不做下划线转驼峰,也不会因为接口文档写了
就自动把
映射过去。你看到的空值,大概率是字段根本没被识别到,而不是“传了但丢了”。
JsonRpcRequestDTOHyperf\Utils\Codec\JsonRequestDTO@varRequestDTOpublicsetXxx()int $userId$userIdnullarrayarray|UserDto[] $users{"user_id": 123, "tags": ["a", "b"]}RequestDTOclass UserRequest
{
public int $userId; // ❌ 键是 user_id,不是 userId → 值为 0
public array $tags; // ✅ 正确,但若没加 @var 或没 setter,仍可能为空
}
user_idpublic int $user_id;publicprotectedprivateintstring@var/** @var string */ public $name;public function getUserInfo(UserRequest $request)
{
var_dump($request->toArray()); // 看实际塞进去了哪些字段
// 或更底层:
$raw = $this->container->get(\Psr\Http\Message\ServerRequestInterface::class)->getParsedBody();
var_dump($raw); // 看原始 JSON 解析结果
}
$rawuser_id$request->toArray()user_idnullpublicint@ValidatedAbstractRequestJsonRpcHyperf\JsonRpc\Contract\ParserInterface@ValidateValidator__construct()Hyperf\Validation\RequestuserIduser_id