更新MySQL JSON字段时double值被加双引号如何解决?
问题根因
该问题和PHP侧传入的值类型无关,是illuminate/database本身的逻辑缺陷:组件在处理JSON字段的->快捷更新语法时,会将浮点(double)类型值默认按字符串类型做PDO参数绑定,最终MySQL接收到字符串输入,写入JSON列时就会自动添加双引号存为字符串;整数类型因为组件内部做了特殊类型适配,所以不会出现该问题。
可用修复方案
方案1:用原始表达式包裹浮点值,绕过框架的自动类型转换
直接给浮点值套一层DB::raw(),让框架把值原样传给MySQL,不做字符串类型绑定,写法最简洁:use Illuminate\Support\Facades\DB; $this->table('table') ->where('id', $id) ->update([ 'data->test' => DB::raw(34.55), 'data->test2' => DB::raw(44.99), ]);如果传入的是动态变量,务必先做浮点类型强转再传入
DB::raw(),避免SQL注入风险。方案2:手动调用JSON_SET函数写入
显式写原生JSON更新逻辑,完全控制传入值的类型:use Illuminate\Support\Facades\DB; $this->table('table') ->where('id', $id) ->update([ 'data' => DB::raw(sprintf( "JSON_SET(data, '$.test', %F, '$.test2', %F)", 34.55, 44.99 )) ]);sprintf的%F占位符会自动把传入值格式化为浮点型字符串,安全拼接进SQL语句,避免注入问题。方案3:读取全量JSON字段修改后整体回写
先查询出记录的data字段原值,在PHP侧修改对应键值(保持double类型),再整体编码为JSON回写,框架对整个JSON列的写入会做正确的类型处理:$record = $this->table('table')->where('id', $id)->first(); $data = json_decode($record->data, true); $data['test'] = 34.55; $data['test2'] = 44.99; $this->table('table') ->where('id', $id) ->update([ 'data' => json_encode($data) ]);该方案会额外产生一次查询开销,适合低并发场景使用。
内容的提问来源于stack exchange,提问作者emrez
相关产品推荐
相关产品推荐

