You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:00:38