Backpack 6.5.1可重复字段嵌套上传字段时JSON编码报错求助
问题:Backpack 6.5.1中Repeatable嵌套Upload字段导致JSON编码错误
场景与配置
在Backpack 6.5.1版本中,使用Repeatable字段嵌套基于Backpack上传器的文件上传字段,相关配置如下:
CRUD字段配置
$this->crud->addField([ // repeatable 'name' => 'blocks', 'label' => 'Downloads', 'type' => 'repeatable', 'subfields' => [ [ 'name' => 'title', ], [ 'name' => 'description', 'type' => 'ckeditor' ], [ 'name' => 'file', 'label' => 'File', 'type' => 'upload', 'disk' => 'public', 'withFiles'=> true, ], ], 'new_item_label' => 'Add File', 'reorder' => true, 'init_rows' => 0, 'min_rows' => 0, 'tab' => 'Files', ]);
模型代码
模型中将blocks字段转换为数组:
class Page extends BackpackPage { use CrudTrait, RevisionableTrait; use HasFactory, SoftDeletes, OpenPageLink; use Sluggable; protected $fillable = [ 'slug', 'name', 'title', 'body', 'blocks', 'lists', 'template', ]; protected $casts = [ 'id' => 'integer', 'blocks' => 'array', 'lists' => 'array', ]; protected $fakeColumns = [ 'blocks', 'lists', ]; }
数据库表结构
blocks字段为可空JSON类型:
id bigint unsigned NO PRI NULL auto_increment slug varchar(255) NO NULL name varchar(50) NO NULL title varchar(255) NO NULL body text NO NULL blocks json YES NULL lists json YES NULL template varchar(50) YES NULL created_at timestamp YES NULL updated_at timestamp YES NULL deleted_at timestamp YES NULL
问题现象
编辑或保存带有已上传文件的模型时,出现JSON编码错误;移除Repeatable字段中的Upload字段后,功能恢复正常。此前通过关联表实现该功能,但希望将文件信息以JSON格式存储。
解决方案
问题根源是Repeatable嵌套Upload字段时,上传的UploadedFile对象会被保留在数组中,而JSON无法序列化对象。需手动处理文件上传,将对象转换为可序列化的路径或信息:
1. 修改CRUD字段配置
移除withFiles=true,避免自动处理导致对象残留,同时添加已上传文件的显示逻辑:
[ 'name' => 'file', 'label' => 'File', 'type' => 'upload', 'disk' => 'public', // 移除withFiles=true,改为手动处理上传 'value' => function($entry, $field) { // 显示当前repeatable项的已上传文件路径 $currentBlock = $field->getRepeatableCurrentItem(); return $currentBlock['file'] ?? null; }, 'preview' => function($value) { // 可选:添加文件预览链接 return $value ? asset('storage/' . $value) : null; }, ],
2. 在CrudController中添加保存回调
手动处理每个Repeatable项的文件上传:
// 在setupCreateOperation和setupUpdateOperation方法中添加以下代码 $this->crud->beforeSave(function ($entry) { $this->processRepeatableFiles(); }); $this->crud->beforeUpdate(function ($entry) { $this->processRepeatableFiles(); }); // 定义文件处理函数 private function processRepeatableFiles() { $blocks = request()->input('blocks', []); foreach ($blocks as &$block) { // 处理新上传的文件 if (isset($block['file']) && $block['file'] instanceof \Illuminate\Http\UploadedFile) { // 上传到指定磁盘和目录 $path = $block['file']->store('downloads', 'public'); // 将文件路径存入数组 $block['file'] = $path; } else { // 编辑时保留旧文件路径,空值则移除字段 if (empty($block['file'])) { unset($block['file']); } } } // 更新请求中的blocks数据 request()->merge(['blocks' => $blocks]); }
3. 保持模型配置不变
模型中的casts和fakeColumns配置无需修改,确保JSON与数组的自动转换正常。
内容的提问来源于stack exchange,提问作者Rob Curle
相关产品推荐
相关产品推荐

