在thinkphp 8.0中操作mysql 8.0 json字段需严格匹配字段类型:先用show columns确认type为json,再用->>>语法查询或json_set/json_replace更新,避免双重编码、引号错误和null陷阱。

在ThinkPHP 8.0中精准查出MySQL 8.0原生JSON字段里的值、安全更新嵌套键、避免查询为空或报错,必须绕开框架默认解析陷阱,直接对接MySQL原生JSON语法层——这一步做错,where条件永远不生效,update后字段变NULL或乱码。
确认JSON字段可用前提
执行 SHOW COLUMNS FROM user LIKE 'info';,检查Type列是否显示json;再运行 SELECT VERSION();,确保返回值≥5.7.0。若Type是text或varchar,【不要强行使用->>语法】,否则MySQL会报FUNCTION database.JSON_UNQUOTE does not exist错误。
字段类型不匹配时,改用whereRaw('JSON_EXTRACT(info, "$.email") = ?', [$email]),但注意此处$email必须是带双引号的合法JSON字符串,例如"\"test@example.com\""。
查询JSON对象中的键值
方法一:使用->>语法(推荐)
直接写where('info->>email', 'test@example.com'),MySQL自动调用JSON_UNQUOTE(JSON_EXTRACT(info, "$.email")),返回无引号纯字符串,可安全用于=、>、LIKE比较。
方法二:用whereRaw精确控制whereRaw('info->>"$.status" = ?', ['active']),适合需要嵌套路径或动态拼接的场景,但要自己处理引号和参数绑定。
⚠️切记:where('info->status', 'active')返回的是带引号字符串"active",PHP中与裸字符串'active'比较永远为false——这是最常踩的坑。
查询JSON数组是否包含某元素
第一步:用户输入必须先转为合法JSON字符串$tag = json_encode($userInput, JSON_UNESCAPED_UNICODE);,否则whereJsonContains('tags', $userInput)会生成JSON_CONTAINS(tags, php)这种非法SQL,MySQL直接报错。
第二步:指定JSON路径防止误匹配whereRaw('JSON_CONTAINS(tags, ?, "$.skills")', [$tag]),强制只在skills子数组中查找,避免同名字段(如info.skills和profile.skills)冲突。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
第三步:验证结果是否为空数组
即使语法全对,若表中该字段值为null或非JSON格式字符串,JSON_CONTAINS也返回0,查询结果为空——需提前用whereNotNull('tags')过滤。
写入JSON字段的两种方式
方式1:整字段覆盖写入Db::table('user')->json(['info'])->insert(['info' => ['email' => 'a@b.com', 'age' => 25]]);,json(['info'])声明后,框架自动对info值做json_encode并设为UTF-8无转义。
方式2:模型中声明$type + 修改器(仅适用于TEXT/VARCHAR字段)
在模型类中定义:protected $type = ['data' => 'json'];,读取时自动json_decode($val, true);写入时仍需手动处理或配修改器:public function setDataAttr($value) { return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); }。
【别混用:原生JSON字段+$type=['field'=>'json']会导致写入异常】,TP会尝试encode已是JSON的字符串,结果变成双重编码。
更新JSON字段中的单个键值
① 使用Db::raw()调用MySQL原生函数Db::table('user')->where('id', 1)->update(['info' => Db::raw('JSON_SET(info, "$.email", "new@b.com")')]);
② 使用whereRaw + JSON_REPLACEDb::table('user')->whereRaw('id = ? AND JSON_EXTRACT(info, "$.email") IS NOT NULL', [1])->update(['info' => Db::raw('JSON_REPLACE(info, "$.email", "new@b.com")')]);,加IS NOT NULL判断可避免对空JSON字段执行替换导致整字段被置为NULL。
③ 在模型中封装更新逻辑(推荐)
定义方法:public function updateEmail($email) { return $this->save(['info' => Db::raw("JSON_SET(info, '$.email', '" . addslashes($email) . "')")]); },注意手动addslashes防注入,且仅限简单字符串值;含引号或特殊字符时必须用参数绑定+whereRaw替代。










