
本文介绍当 laravel 模型字段以 json 字符串形式(如 {"en":"...","ar":"..."})存入数据库时,如何绕过自动反序列化逻辑,安全获取未经处理的原始 json 字符串值。
本文介绍当 laravel 模型字段以 json 字符串形式(如 {"en":"...","ar":"..."})存入数据库时,如何绕过自动反序列化逻辑,安全获取未经处理的原始 json 字符串值。
在 Laravel 应用中,若将多语言内容(如 title、description)以 JSON 字符串格式直接存入数据库文本字段(例如 VARCHAR 或 TEXT),需特别注意模型访问行为:Laravel 默认不会对普通字符串字段做 JSON 解析;但若该字段被声明为 casts 中的 'json' 类型,框架会自动调用 json_decode() 并返回 PHP 数组/对象——这正是问题根源。
观察示例数据:
$plan = Plan::where('id', 15)->first();
// 输出显示 title 值为 '{"en":"title eng","ar":"gf"}'(带引号的字符串)此时 $plan->title 返回 "title eng",说明模型中已定义了类似如下访问器(Accessor):
public function getTitleAttribute($value)
{
return json_decode($value, true)['en'] ?? '';
}该访问器将原始 JSON 字符串解析后取 en 键值,导致无法直接获取原始 JSON。
✅ 正确获取原始 JSON 字符串的方法是跳过所有访问器与类型转换,直取底层属性值:
使用 getAttributes() 方法获取模型原始属性数组,再从中提取指定键:
$rawTitleJson = $plan->getAttributes()['title'];
// 返回字符串:'{"en":"title eng","ar":"gf"}'
// 验证是否为有效 JSON(推荐生产环境增加校验)
if (is_string($rawTitleJson) && json_validate($rawTitleJson)) {
$data = json_decode($rawTitleJson, true);
echo $data['en']; // "title eng"
echo $data['ar']; // "gf"
}⚠️ 注意事项:
- ❌ 不要使用 $plan['title'] 或 $plan->title —— 前者触发 ArrayAccess(仍走访问器),后者直接调用访问器;
- ❌ 避免重复 json_decode(json_encode(...)) 或对已解析结果再解码(易出错且低效);
- ✅ 若需频繁操作原始 JSON 字段,建议在模型中显式定义一个「原始字段」访问器,提升可读性与复用性:
public function getRawTitleAttribute() { return $this->getAttributes()['title'] ?? null; } // 使用:$plan->raw_title - ? 安全提示:从数据库读取的 JSON 字符串应始终通过 json_validate()(PHP 8.0+)或 json_last_error() === JSON_ERROR_NONE 校验有效性,防止解析失败引发异常。
总结:当 Laravel 模型存在 JSON 字符串字段且被访问器封装时,getAttributes() 是获取原始存储值的最可靠方式。它绕过所有 Eloquent 的属性访问逻辑,直达底层数据源,是处理“伪 JSON 字段”(即未启用 casts=['field' => 'json'],但内容为 JSON 字符串)的标准实践。










