Yii2存入MySQL JSON字段时JSON带反斜杠损坏问题排查
Yii2存储JSON字段出现反斜杠转义问题
问题现象
在Yii2开发过程中,将关联数组存入MySQL数据表的JSON类型字段时,最终保存的值是带有\反斜杠的损坏JSON对象。
phpMyAdmin中查看的异常效果:
对应数据保存逻辑代码:
// 更新动作代码片段 //... if ($flag) { $transaction->commit(); Yii::$app->getSession()->setFlash('success', 'Record has been updated!'); $this->savedi($model); return $this->redirect(['view', 'id' => $model->id]); } //... private function savedi($model) { $output = []; foreach ($model->invoiceItems as $i => $item){ $output['items'][$i]['id'] = $item->item_id; $output['items'][$i]['title'] = $item->item->title; $output['items'][$i]['qty'] = $item->qty; } $model->saved = json_encode($output); $model->save(); }
问题原因
核心原因是JSON双重编码:
Yii2的ActiveRecord内置了JSON字段的自动序列化/反序列化机制,只要模型规则中配置了字段为JSON类型,框架保存数据时会自动将数组/对象类型的属性值编码为JSON字符串存入数据库,读取时也会自动将JSON字符串解码为PHP数组,无需手动做编码处理。
上述代码中手动调用json_encode()将数组转为JSON字符串后再赋值给字段,框架保存时会把这个已经是JSON格式的字符串当做普通字符串再次做JSON编码,转义字符串内的双引号,最终存储的内容就会出现大量反斜杠,变成转义后的字符串而非合法JSON对象。
修复方案
移除手动调用的json_encode(),将组装好的PHP数组直接赋值给字段,交给Yii2框架自动完成JSON编码即可,修改后的savedi方法代码:
private function savedi($model) { $output = []; foreach ($model->invoiceItems as $i => $item){ $output['items'][$i]['id'] = $item->item_id; $output['items'][$i]['title'] = $item->item->title; $output['items'][$i]['qty'] = $item->qty; } // 直接赋值数组,无需手动编码 $model->saved = $output; $model->save(); }
前置校验:需要确认模型的
rules()方法中已经为saved字段配置了JSON验证规则,参考配置:public function rules() { return [ // 其余业务规则... [['saved'], 'json'], ]; }配置后框架才能正确识别该字段类型,自动完成序列化、反序列化处理。
不推荐采用手动编码JSON后关闭框架自动转换的方案,该方式会破坏框架的字段类型自动处理逻辑,后续读取字段值时需要额外手动解码,增加冗余代码。
内容的提问来源于stack exchange,提问作者SaidbakR
相关产品推荐
相关产品推荐

