通过在控制器中添加新数据来动态更新验证规则

时间:2019-05-09 15:42:46

标签: php laravel neoeloquent

我正在开发一个基于Web的应用程序,技术堆栈为: VueJS ,用于表示层, Laravel(PHP),用于 RESTFUL API 服务,以及名为 neo4j 的基于nosql图的数据库。这是问题的上下文,我有一个名为 Post 的模型,并且在此定义的属性将共享所有帖子类型,因此它们都将拥有它:

use NeoEloquent;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Vinelab\NeoEloquent\Eloquent\SoftDeletes;

class Post extends NeoEloquent
{
protected $label = 'Post';
protected $dates = ['created_at', 'updated_at', 'deleted_at'];

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'title',
    'slug',
    'body',
    'status',
    'image',
    'published_at',
    'read_time',
    'isModerate',
    'link',
    'external_id'
];

/**

protected $hidden = ['remember_token'];

/**
 * relations
 */

public function authors()
{
    return $this->belongstoMany('App\User', 'AUTHOR');
}

public function getSlugOptions(): SlugOptions
{
    return SlugOptions::create()->generateSlugsFrom('title')->saveSlugsTo('slug');
}

//Post type
public function contentType(){
  return $this->hasOne('App\ContentType','IS_OF_TYPE');
}
}

PostType :这里的类型可以是文件链接事件等。例如: [name=>'Event','description'=>'description','slug'=>'event']

class PostType extends NeoEloquent
{
    protected $label='ContentType';
    protected $dates=['created_at','updated_at','deleted_at'];

    protected $fillable=[
      "name",
      "description",
      "slug"
    ];

//Ce input contentype sera associe a plusieurs input fields
    public function customFields(){
      return $this->belongsToMany('App\CustomField',"HAS_FIELD");
    }

    public function post(){
      return $this->belongsToMany('App\Post','IS_OF_TYPE');
    }
}

最后是 CustomField 模型:

class CustomField extends NeoEloquent
{
  protected $label="CustomType";
  protected $dates=["created_at","updated_at","deleted_at"];

  protected $fillable=[
    "field_name",
    "field_type",
    "field_order",
    "validation_rules"
  ];


  public function contentTypes(){
    return $this->belongsToMany('App\CustomField','HAS_FIELD');
  }
}

因此,流程如下: 1-在UI中,当用户首次打开帖子时,创建帖子 Form ,他是fillable模型的Post属性中定义的通用字段。为此,已经有一个表单请求验证定义,如下所示:

class StorePost extends FormRequest
{

    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'title' => 'required|string|min:1',
            'body' => 'required',
            'status' => 'required',
            'image' => 'sometimes|image',
            'published_at' => 'required',
            'link' => 'required_if:type,==,RSS|required_if:type,==,LINK',
            'external_id' => 'sometimes'
        ];
    }
}

2-以相同的形式,用户在type的{​​{1}}字段中加载<select>ContentType模型中的所有内容类型。{{1 }},一旦他选择了一个类型,另一个database(throug ajax)就去检索Eg : Event,Link,File,...。请注意,此处的自定义字段表示,对于类型为request(ajax)的字段,其格式为{{ 1}}等。我使用这些字段属性在CustomField中动态构建我的Event,并且一旦用户填写表单并在后端服务器中发送数据,我就没有了:我首先要做的是为所有自定义['field_name'=>'name','field_type'=>'string','field_order'=>'1',validation_rules=>'required|max:200']创建一个表单请求,但我没有想过是否要拥有PostType fields Front-End我添加20,我不会创建20条验证规则。此时,我的控制器仅知道如何验证“ Post”,如下所示:

inputs field

我想做的是根据来自前端的数据用新的字段和新的规则更新现有的StorePost验证。因此,我不知道如何更新现有的{{1} }在控制器的Requests文件夹中进行定义,并根据来自前端的数据基于前端的定义和填充字段创建新的验证规则。我有一个主意,包括获取所有input_fields验证基于前端发送给我的帖子类型的规则,然后更新现有的验证规则。

注意:我定义冲突关系的方式与Event,File and Link不同,因为我使用的是实现Post types数据库的public function store(StorePost $request) { $data = $request->validated(); ... }

1 个答案:

答案 0 :(得分:1)

您可以使用请求中的数据动态构建验证规则:

use Illuminate\Http\Request;

class StorePost extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules(Request $request)
    {
        $rules = [
            'title' => 'required|string|min:1',
            'body' => 'required',
            'status' => 'required',
            'image' => 'sometimes|image',
            'published_at' => 'required',
            'link' => 'required_if:type,==,RSS|required_if:type,==,LINK',
            'external_id' => 'sometimes'
        ];

        if($typeSlug = $request->get('type'))
        {
            $type = PostType::where('slug', $typeSlug)->with('customFields');

            // map custom fields into a `['name' => 'rules']` format
            $customFieldRules = $type->customFields->mapWithKeys(function($customField) {
                return [$customField->field_name => $customField->validation_rules];
            });

            $rules = array_merge($rules, $customFieldRules);
        }

        return $rules;
    }
}