
在 Laravel Backpack 中使用 upload 字段时,若模型的 firmware 属性未列入 $fillable 数组,则无法通过批量赋值(mass assignment)传递文件数据,导致自定义访问器(Attribute)或传统 mutator 不被调用,文件不上传且数据库字段为空。
在 laravel backpack 中使用 `upload` 字段时,若模型的 `firmware` 属性未列入 `$fillable` 数组,则无法通过批量赋值(mass assignment)传递文件数据,导致自定义访问器(attribute)或传统 mutator 不被调用,文件不上传且数据库字段为空。
这是 Laravel Backpack(及底层 Laravel Eloquent)的一个关键安全机制:只有声明在 $fillable 中的属性才允许通过 create()、update() 或 Backpack 的 CRUD 表单自动填充(auto-fill)进行批量赋值。而 Backpack 的 upload 字段在提交时,会将上传的 UploadedFile 实例作为值,尝试写入模型的 firmware 属性——如果该属性不在 $fillable 中,Laravel 会静默忽略它,既不报错也不调用任何访问器(setFirmwareAttribute 或 Attribute::make(set: ...)),最终导致:
- dd() 不执行,修改器逻辑完全跳过;
- 文件未被处理,uploadFileToDisk() 从未调用;
- 数据库字段因未接收值而保持 NULL(即使字段非空,也会触发 Field doesn't have a default value 错误)。
✅ 正确做法:在模型中显式声明 firmware 为可批量赋值属性:
// app/Models/YourModel.php
class YourModel extends Model
{
protected $fillable = [
// 其他字段...
'firmware', // ✅ 必须添加此项
];
// Laravel 9 推荐的 Attribute 写法(确保已添加 $fillable!)
protected function firmware(): Attribute
{
return Attribute::make(
set: function ($value) {
// $value 是 Illuminate\Http\UploadedFile 实例
if (!$value || !$value->isValid()) {
return null;
}
$disk = 'public'; // 或 'uploads',需与 CRUD 配置一致
$destination_path = 'firmware';
// 使用 Backpack 提供的 uploadFileToDisk 辅助方法
$path = $this->uploadFileToDisk($value, 'firmware', $disk, $destination_path);
// 返回存储路径(如 'firmware/abc123.bin'),将存入 firmware 字段
return $path;
}
);
}
}⚠️ 注意事项:
- $fillable 是前提,缺一不可:无论你使用传统 mutator 还是 Laravel 9+ 的 Attribute,都必须先确保字段可批量赋值;
- 磁盘配置需匹配:CRUD 中 disk => 'uploads' 要求 config/filesystems.php 中存在名为 uploads 的磁盘配置;若使用 public 磁盘,请同步更新 CRUD 配置中的 'disk' => 'public';
- 避免重复处理:Backpack 的 upload 字段本身具备基础上传能力,但若需自定义路径、重命名或校验,应通过 Attribute 的 set 回调实现,而非额外手动调用 uploadFileToDisk 在控制器中;
- 迁移建议:若 firmware 字段原为 NOT NULL,请先运行迁移设为可空,待功能验证无误后,再考虑是否在业务逻辑中强制校验上传必要性(如在 Form Request 中添加 required|file 规则)。
总结:Backpack 的文件上传依赖 Laravel 的批量赋值机制,$fillable 是打通表单 → 模型 → 访问器 → 文件存储链路的关键开关。漏掉它,整个流程将在第一步中断。

















