Laravel 8 Factory写入数据库时data字段值被额外包裹引号问题
问题产生原因
核心原因是你的CouponRule模型中对data字段开启了JSON/数组类型的属性转换($casts)。
你可以检查模型代码,大概率能找到如下配置:
protected $casts = [ 'data' => 'array', // 也可能配置为'json'类型 ];
Laravel的该特性会自动处理字段和JSON格式的双向转换:存库时自动对非字符串值调用json_encode,读取时自动调用json_decode转回数组/对象。当你直接给开启了该转换的字段传入字符串值时,Laravel不会判断字符串是否已经是JSON格式,会直接把传入值当做普通字符串执行json_encode。
你可以直接执行PHP代码验证:echo json_encode("{'min': 100}");,输出结果就是你在数据库中看到的"{'min': 100}"——字符串经过JSON编码后,会被自动包裹一层双引号,这就是额外引号的来源。
额外提一句:你当前传入的{'min': 100}本身也不是合法JSON格式,标准JSON要求键名、字符串值必须使用双引号包裹,单引号格式的内容在后续JSON解析时会直接报错。
修复方案
根据你的实际需求选对应方案即可:
- 推荐方案:保留模型的类型转换配置,工厂定义中直接给
data字段传数组,不要传字符串,Laravel会自动将其转为标准JSON格式存库:
public function definition() { return [ 'coupon_id' => 286, 'coupon_rule_type_id' => 8, 'data' => ['min' => 100], // 直接传数组,最终存库内容为标准JSON: {"min":100} 'created_at' => now(), 'updated_at' => now(), ]; }
这种写法后续从模型读取data字段时可以直接拿到数组使用,不需要手动做JSON解码,是Laravel官方推荐的JSON字段处理方式。
- 如果你不需要Laravel自动处理
data字段的格式转换,想要完全手动控制存入的内容,直接把CouponRule模型$casts配置中data字段对应的转换规则删掉即可。注意这种方式下你需要自己保证存入内容的格式符合业务预期,避免出现解析错误。 - 不推荐方案:如果需要保留类型转换,又要临时传入原始字符串存库,可以通过
DB门面直接写入、或者调用forceFill绕过模型赋值逻辑,但这种方式很容易造成字段数据格式不统一,后续维护成本极高。
内容的提问来源于stack exchange,提问作者Adam Hopkinson
相关产品推荐
相关产品推荐

