Laravel-admin 中 $form->table 图片上传时的 bug 问题

问题说明:$form->table 图片上传后,再次编辑并提交后,会丢失图片数据

具体如下:

使用的是laravel-admin的JSON组件
问题代码存在与下面的$form->table

protected function form()
{

  $form = new Form(new Good());
    ……
    $form->table('size', function ($table) {
      $table->text('sizes', __('规格大小'));
      $table->text('colors', __('颜色分类'));
      $table->text('sales', __('价格'));
      $table->text('sizecostprice', __('成本价格'));
      $table->text('sizestock', __('库存'));
      $table->image('sizeimg', __('图片'));
    });
    ……
}

前端展示界面如下:
laravel-admin 中 $form->table 图片传时的bug问题

加上上面代码后,前台界面显示、上传图片操作、确认提交等操作都正常;
添加完成后,再次编辑该数据,也可以正常显示;

问题在于,在编辑页面,不做任何改动直接提交后,$table->image('sizeimg', __('图片'));的数据丢失了!

尝试查找原因

分别在新增和编辑时,打印$form数据,结果显示
新增时:
laravel-admin 中 $form->table 图片传时的bug问题

编辑后提交(不做任何改动,如果编辑时重新上传图片,还是可以正常存储到数据库的):
laravel-admin 中 $form->table 图片传时的bug问题

可以看到,新增时,sizeimg是存在的,是一个文件对象;编辑提交后,sizeimg丢失了

发现编辑时sizeimg不存在的问题后,考虑到是不是编辑时没有加载该参数input元素,所以又到前台编辑页面去查找,结果发现是有的,如下图:
laravel-admin 中 $form->table 图片传时的bug问题
可以看到,sizeimg跟其他的$table->text()的字段都是同样存在的,但是不明白为什么在提交后会丢失

至此,个人能想到的是,应该是laravel-admin的 $form->table()方法不能很好地支持$table->image()方法,导致的这个问题

希望路过的高手,能够帮忙想出解决办法,谢谢!

最后贴一下关于这个方法官方文档的使用说明:

laravel-admin 中 $form->table 图片传时的bug问题

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

在Good模型中加入:

  public function setSizeAttribute($extra){
    //设置了值,说明是编辑操作
    if (isset($this->attributes['size'])){
        $old_content = json_decode($this->attributes['size'],true);
        foreach ($extra as $key => &$val) {
            // 如果旧数据未删除,且当前不存在图片,则将旧图片路径添加进去
            if (isset($old_content[$key]) && !isset($val['img'])) {
                $val['img'] = $old_content[$key]['img'] ?? '';
            }
        }
    }
    $this->attributes['attr'] = json_encode(array_values($extra));
}
3年前 评论
acvc225 (楼主) 3年前
acvc225 (楼主) 3年前
她来听我的演唱会 (作者) 3年前
helojianxin 3年前
讨论数量: 7
grubby

mark 同样的困扰

3年前 评论

大哥,有没有解决方法,我也遇到了这个问题

3年前 评论
acvc225 (楼主) 3年前
Natural

+1

3年前 评论
zheng_97 3年前

多图上传同样困扰,目前做法是如果客户端传来了null直接忽略

3年前 评论

在Good模型中加入:

  public function setSizeAttribute($extra){
    //设置了值,说明是编辑操作
    if (isset($this->attributes['size'])){
        $old_content = json_decode($this->attributes['size'],true);
        foreach ($extra as $key => &$val) {
            // 如果旧数据未删除,且当前不存在图片,则将旧图片路径添加进去
            if (isset($old_content[$key]) && !isset($val['img'])) {
                $val['img'] = $old_content[$key]['img'] ?? '';
            }
        }
    }
    $this->attributes['attr'] = json_encode(array_values($extra));
}
3年前 评论
acvc225 (楼主) 3年前
acvc225 (楼主) 3年前
她来听我的演唱会 (作者) 3年前
helojianxin 3年前

之前写博客站点配置时也遇到类似的问题,编辑时图片字段是没有的,也无法知道图片是否要删除。我是把配置保存在一个文件里面的,使用laravel-admin的数据表单功能。贴一下我的解决方法,以供参考:

  1. 给要操作的元素添加事件监听(例如这里给删除按钮添加一个点击事件,来添加删除的数据标记):
    class SettingsController extends Controller
    {
     public function settings(Content $content)
     {
         Admin::script(<<< JS
     // 点击 X 按钮时标记图片已经移除,不然后端无法知道
     $('#pjax-container').on('click', '.fileinput-remove', function() {
         let field = $(this).closest('.file-input').find("input[type='file']").attr('name');
         var input = document.createElement("input");
         input.type = "hidden";
         input.name = "removed_image[]";
         input.value = field;
         $(this).closest('.file-input').append(input);
     })
    JS
         );
         return $content
             ->title('网站设置')
             ->body(new Setting());
     }
    }
  1. 数据保存时的处理(判断有新的图片上传,保存新的;没有则判断有没有删除标记,没有删除标记则把原来旧的值赋值给新的数据):
public function handle(Request $request){
        $data = $request->except(['logo', 'qr_weapp', 'qr_wechat_office', 'avatar', 'removed_image']);

        $uploader = app(ImageUploader::class);
        $originalConfigs = config('site');

        // 上传图片
        foreach (['logo', 'qr_weapp', 'qr_wechat_office'] as $field) {
            if ($file = $request->file($field)) {
                $result = $uploader->save($file, 'site', 1024);
                if ($result) {
                    $data[$field] = $result['path'];
                }
            } else {
                // 如果原来有值,根据移除标记判断下要不要保持
                if(!empty($originalConfigs[$field])) {
                    if($request->has('removed_image')) {
                        if(!in_array($field, $request->get('removed_image'))) {
                            $data[$field] = $originalConfigs[$field];
                        }
                    } else {
                        // 没有任何移除标记,都保持
                        $data[$field] = $originalConfigs[$field];
                    }
                }
            }
        }


 .
 .
 .

        admin_success('修改成功');

        return redirect(url('admin/settings'));
    }

相关修复提交记录:
github.com/HubQin/QinBlog/commit/f...

3年前 评论
acvc225 (楼主) 3年前

file

file 也遇到过,不知道是不是最简单的处理方式,只使用于单图片

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!