Laravel Nova:将字段动态绑定到模型上的 JSON 属性

Hei*_*inz 0 laravel eloquent laravel-nova

拉拉维尔·诺瓦

对于特定项目,我想结合使用 Nova Resource UI 的强大功能和更灵活的数据模型。具体来说,我希望能够将字段添加到存储在 JSON 数据库字段中而不是表中的属性的资源中。

规格:

数据库模型:报价(含迁移)

public function up()
{
    Schema::create('quotations', function(Blueprint $table)
    {
        $table->bigInteger('id', true);
        $table->timestamps();
        $table->string('client_name', 100)->nullable();
        $table->string('client_surname', 100)->nullable();
        $table->string('status', 10)->nullable()->default('NEW');
        $table->text('data')->nullable();
    });
}
Run Code Online (Sandbox Code Playgroud)

新星资源

因此,我可以定义一个“正常”NOVA 资源,并在 App\Nova\Quotation 中定义以下字段(*忽略状态):

public function fields(Request $request)
{
    return [
        Text::make('Client Name')->sortable(),
        Text::make('Client Surname')->sortable(),


    ];
}
Run Code Online (Sandbox Code Playgroud)

现在我的“愿望”是达到这种效果,使用不存在的“bindTo”方法来说明我想要实现的目标

public function fields(Request $request)
{
    return [
        Text::make('Client Name')->sortable(),
        Text::make('Client Surname')->sortable(),

        //Fields bound into the JSON data property  
        Text::make('Client Id')->bindTo('data.client_id),
        Date::make('Client Date Of Birth')->bindTo('data.client_date_of_birth),

        //etc       


    ];
}
Run Code Online (Sandbox Code Playgroud)

因此,当保存报价模型时,client_name 和 client_surname 属性将正常保存到数据库中。但 client_id 和 client_date_of_birth 应保存到 JSON 数据属性。

我知道我可以在报价模型上设置一个 Mutator

public function setClientIdAttribute($value)
{
      set_data($this->data,'client_id',$value);
}
Run Code Online (Sandbox Code Playgroud)

然而,这仍然需要一个“非动态”报价模型。我希望能够动态地将字段添加到视图中,而无需在基础知识之外更改报价模型。现实世界的示例是,不同的产品在生成报价之前需要收集不同的输入字段。然后,我可以轻松地将字段定义动态注入 Nova 资源中,同时保持数据库模型简单。

我还尝试了对一个简单问题的回答: Laravel Model Dynamic Attribute

然而,所提出的解决方案不起作用,因为 Nova 仍在寻找表上的属性。

我很想获得一些关于如何满足这一要求的意见。

小智 5

你可以这样做:

// Model
protected $casts = [
    'data' => 'array'
];

// Nova Resource  
Text::make('Client Id', 'data->client_id')->resolveUsing(function ($value) {
   return $value;
}),
Run Code Online (Sandbox Code Playgroud)