laravel-admin json字段新增不成功或报错解决办法

卢皓轩
2023-12-01

在使用laravel-admin的模型表单的时候,有个字段是json格式,新增的时候总是不能成功,经过排查源代码,发现他在校验有效column的时候,会根据form提交的字段进行null判断,源码位置如下:

D:\WWW\xxx\vendor\encore\laravel-admin\src\Form.php line :900

protected function prepareInsert($inserts): array
{
    if ($this->isHasOneRelation($inserts)) {
        $inserts = Arr::dot($inserts);
    }

    foreach ($inserts as $column => $value) {
        if (($field = $this->getFieldByColumn($column)) === null) {// 就是这里
            unset($inserts[$column]);
            continue;
        }

        $inserts[$column] = $field->prepare($value);
    }

    $prepared = [];

    foreach ($inserts as $key => $value) {
        Arr::set($prepared, $key, $value);
    }

    return $prepared;
}

可以把提交的form数据打印出来,就能看得很清楚了.

dd($this->fields(),$inserts,$column);

改正方法如下,把json_content设置成hidden,这样的话laravel-admin就会判断出是存在这个字段,json.然后设置对应模型cast即可.但是好像还有另外一种官方的用法,用embed标识,在最后.
我之所以没有使用官方的,是因为我的数据给是变化比较大,不是规整的一维或者二维数据.

protected $casts = [
    'json_content' => 'json',
    'xxx' => 'json',
];

// key被覆盖,重新生成key
public function getProductsAttribute($products)
{
    return array_values(json_decode($products, true) ?: []);
}
public function form()
{
    $form = new Form(new XXX());
    $form->text('name', '活动名称')->required();
    $form->text('slug', '活动Slug')->required();

    $$xxx = [];
    if ($form->isEditing()) {
        // 获取路由参数
        $form->datetime('created_at', '创建时间')->readonly();
    }

    $form->table('products', '活动产品', function ($table) {
        $table->select('product_id', '产品')->options(function ($id) {
            $product = Product::find($id);
            return $product ? $product->pluck('pro_name', 'id') : [];
        })->ajax('/admin/api/xxx');

        $table->select('type', '权益类型')->options(self::TYPES);
        $table->number('value', '数值');
    });

    $form->multipleSelect('language', '语言')->options(array_combine(Launch::LANGUAGES, Launch::LANGUAGES));

    $form->hidden('json_content');// 必须要有这个,json_否则会报错content字段不存在\vendor\encore\laravel-admin\src\Form.php Line:900
    $form->url('json_content.first_image', '首图')->required();
    $form->text('json_content.description', '权益{X}')->required();
    $form->textarea('json_content.right_detail', '权益详情{Y}');
    $form->url('json_content.rights_and_images.0.image', '权益图{1}');
    $form->url('json_content.rights_and_images.1.image', '权益图{2}');
    $form->url('json_content.rights_and_images.2.image', '权益图{3}');
    $form->text('json_content.rights_and_images.0.right', '权益描述{a}');
    $form->text('json_content.rights_and_images.1.right', '权益描述{b}');
    $form->text('json_content.rights_and_images.2.right', '权益描述{c}');

    $form->datetimeRange('start_time', 'end_time', '活动时间')->required();
    $form->select('status', '活动状态')->options(VipActivity::STATUS)->default(VipActivity::STATUS_VALID);
    $form->select('style', '按钮样式')->options(VipActivity::STYLES)->default(VipActivity::STYLE_MORE);
    $form->url('redirect', '跳转链接')->required();

    if ($form->isEditing()) {
        $form->url('link', '活动链接');
    }

    // hook 保存后拿到活动id然后再次保存,没有观察者好用,但是不知道观察者为啥不可用
    $form->saved(function (Form $form) {
        $$xxx = $form->model();
        $$xxx->link = vsprintf(config('app.url') . '/share/%s?xxx=%d', [$$xxx->slug, $$xxx->id]);
        $$xxx->save();
    });

    $form->footer(function ($footer) {
        // 去掉`查看`checkbox
        $footer->disableViewCheck();
    });
    // $form->confirm('确定创建吗?', 'create');
    // $form->confirm('确定更新吗?', 'edit');
    return $form;
}
$form->embeds('column_name', function ($form) {

    $form->text('key1')->rules('required');
    $form->email('key2')->rules('required');
    $form->datetime('key3');

    $form->dateRange('key4', 'key5', '范围')->rules('required');
});

// 自定义标题
$form->embeds('column_name', '字段标题', function ($form) {
    ...
});

参考:官方链接

 类似资料: