
本文讲解如何在 Laravel 中正确处理 JSON 类型字段的空值问题,避免将空请求存为 [null],并提供模型层自动转换、数据库查询适配及安全存取的完整解决方案。
本文讲解如何在 laravel 中正确处理 json 类型字段的空值问题,避免将空请求存为 `[null]`,并提供模型层自动转换、数据库查询适配及安全存取的完整解决方案。
在 Laravel 中使用 json 数据类型配合 array 类型转换($casts)时,一个常见陷阱是:当 $request->input('email_signature') 为空(如未提交、提交空数组或空字符串)时,框架默认会将 null 或空值序列化为 ["null"] 或 [null],而非数据库真正的 NULL 值。这导致 whereNotNull('email_signature') 查询失效——因为字段实际存储的是非 NULL 的 JSON 数组,而非 SQL NULL。
✅ 正确做法:在赋值前主动归一化空值
不要直接赋值 $request->input(),而应在控制器或访问器中做预处理:
// Controller
$emailSignature = $request->input('email_signature');
// 归一化:空数组、null、空字符串 → PHP null
if (empty($emailSignature) || $emailSignature === [] || $emailSignature === '') {
$system->email_signature = null; // 显式设为 null,Laravel 会存为 SQL NULL
} else {
$system->email_signature = $emailSignature; // 保持原数组结构
}
$system->save();
✅ 进阶方案:通过 Mutator 统一处理(推荐)
在 Eloquent 模型中定义 setEmailSignatureAttribute mutator,实现逻辑复用与一致性:
// App\Models\System.php
protected $casts = [
'email_signature' => 'array'
];
protected function setEmailSignatureAttribute($value)
{
// 若传入 null、[]、''、['null']、[null] 等语义空值,统一转为 PHP null
if ($value === null || $value === [] || $value === '' ||
(is_array($value) && count($value) === 1 && in_array($value[0], [null, 'null'], true))) {
$this->attributes['email_signature'] = null;
return;
}
// 其他情况正常赋值(Laravel 会自动 json_encode)
$this->attributes['email_signature'] = $value;
}
✅ 此时 whereNotNull('email_signature') 可精准命中真实有数据的记录;whereNull('email_signature') 也能准确查出未设置签名的系统项。
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
? 查询 [null] 遗留数据(兼容过渡期)
若数据库中已存在 [null] 数据,可临时用 JSON 函数清洗:
// 查找所有“逻辑上为空”的 email_signature(含 NULL 和 [null])
System::where(function ($q) {
$q->whereNull('email_signature')
->orWhereRaw("JSON_LENGTH(email_signature) = 1 AND JSON_EXTRACT(email_signature, '$[0]') IN ('null', NULL)");
})->get();
⚠️ 注意:
JSON_EXTRACT行为因 MySQL 版本略有差异,生产环境建议先用DB::select()验证表达式结果。
✅ 最佳实践总结
-
永远显式控制空值:不要依赖
input()的原始返回,务必在业务层判断并转换; - 优先使用 Mutator:比控制器重复逻辑更健壮、可维护;
-
迁移兼容性:已有
[null]数据建议执行一次性清洗:System::whereRaw("JSON_LENGTH(email_signature) = 1 AND JSON_EXTRACT(email_signature, '$[0]') = 'null'") ->update(['email_signature' => null]); -
前端配合:确保表单未填写时
email_signature字段不被提交(如移除),从源头减少歧义。
遵循以上方式,即可让 email_signature 字段真正符合「有/无」二元语义,使 whereNull() / whereNotNull() 查询可靠、高效且语义清晰。










