hyperf 3.1 中需用 whereraw("json_contains_path(config, 'one', '$.timeout')") 查询 json 字段是否包含指定键,并通过 $casts 配置 'config' => 'array'/'object'/'collection' 实现自动转换;同时须重写 setattribute 拦截非法 json 赋值以避免静默失败。

Hyperf 3.1 中需对 MySQL JSON 字段执行「包含某个键」的条件查询,同时确保 JSON 字段在模型层正确转为 PHP 数组或对象,避免类型丢失或解析失败。
MySQL JSON字段中查询是否包含指定键
Hyperf 3.1 原生支持 JSON_CONTAINS_PATH 函数,但 QueryBuilder 封装有限,需手动拼接 SQL 片段。
在模型查询中使用 whereRaw 调用 MySQL 内置函数:JSON_CONTAINS_PATH(column, 'one', '$.key_name')。
注意:第二个参数必须是 'one'(查是否存在任意一个路径)或 'all'(查所有路径),不能写成字符串变量;【'one' 和 'all' 必须用单引号包裹,且不能动态拼接】。
例如查询 config 字段是否含 timeout 键:->whereRaw("JSON_CONTAINS_PATH(config, 'one', '$.timeout')")。
JSON字段自动转为PHP数组或对象
Hyperf 3.1 的 $casts 支持 'json' 类型,但需明确指定目标结构。
方法一:转为关联数组 —— 设置 'config' => 'array',适用于键值可变、需遍历的场景。
方法二:转为 StdClass 对象 —— 设置 'config' => 'object',适合固定结构、链式访问(如 $model->config->host)。
方法三:转为 Collection —— 设置 'config' => 'collection',获得 Laravel 风格的集合方法(map、filter 等),但会额外消耗内存。
⚠️ 若 JSON 字段内容为空字符串 "" 或 null,array 和 object cast 会分别返回空数组 [] 和空对象 stdClass,而 collection 会抛出 TypeError。
处理非法JSON导致的模型赋值失败
第一步:在模型中重写 setAttribute 方法,拦截 JSON 字段赋值。
第二步:对传入值做 is_string 判断,再用 json_decode($value, true) 验证是否合法;若失败则抛出自定义异常或设为 null。
第三步:调用父类 setAttribute 继续后续流程。
这一步必须做,否则非法 JSON(如缺少引号、尾随逗号)会在 save() 时静默转为空字符串写入数据库,后续读取始终为空,排查成本极高。
示例片段:if ($key === 'config' && is_string($value) && json_last_error() !== JSON_ERROR_NONE) { throw new InvalidArgumentException('Invalid JSON for config field'); }











