【问题标题】:Update dynamically validation rules by adding new data in the controller通过在控制器中添加新数据来动态更新验证规则
【发布时间】:2019-09-27 12:13:21
【问题描述】:

我正在开发一个基于 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 : 这里的类型可以是 FileLinkEvent 等。例如: [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 - 在用户第一次打开帖子创建帖子Form时的UI中,他作为fillablePost模型的fillable属性中定义的常用字段。为此,已经有一个表单验证请求定义如下:

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 - 在同一个表单中,用户在<select> 中有type 字段,该字段从database(throug ajax).Eg : Event,Link,File,... 中的ContentType 模型加载所有内容类型,并且一旦他选择了另一个类型@ 987654333@ 去检索CustomField。请注意,这里的自定义字段意味着,对于Event 类型的字段以以下格式发送['field_name'=>'name','field_type'=>'string','field_order'=>'1',validation_rules=>'required|max:200'] 等。我使用这些字段属性来动态构建我的@ Front-End 中的 987654337@,一旦用户填写表单并在后端服务器中发送数据:我不知道如何处理验证。我首先做的是创建一个表单请求我所有的自定义inputs field,但不,我想如果不只是有Event,File and LinkPost types,我添加20。我不会创建20个验证规则。此时我的控制器只知道如何验证“发布”这样:

public function store(StorePost $request)
    {
        $data = $request->validated();
        ...
}

我想做的是根据来自前端的数据使用新字段和新规则更新现有的 StorePost 验证。所以我不知道如何更新现有的 Form Request 定义在我的控制器的 Requests 文件夹中,并基于来自前端的数据创建了基于前端定义和填充字段的新验证规则。我有一个想法,包括获取所有基于 input_fields 验证规则在前端发送给我的 posttypes 上,然后更新现有的验证规则。

注意:我定义 relashionship 的方式与 Eloquent 不同,因为我使用的是实现 neo4j 数据库的 Neoloquent

【问题讨论】:

  • 您能否提供一个请求的有效负载样本以创建Post?我的意思是,类型等。
  • 好的,在前面我会有这个axios.post('http://localhost:5000/api/posts',post),其中post 对象具有以下结构:{title:'Mo titre',slug:'mon-titre',body:'This is the body',status:'my status',image:'base64_image',published_at:'the date',isModerate:false,link:'www.thelink.com',external_id:'the id',content_type:'content_type_id',custom_field_name:'value',custom_fileld_slug:'value',custom_field_slug:'slug'} ...这是有效负载的结构,在服务器中,我们已经有了每个 custom_field 的验证规则,因为只有名称将被发送到 Vue 中的构建表单

标签: php laravel neoeloquent


【解决方案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;
    }
}

【讨论】:

  • $typeSlug 变量从何而来?
  • 以下评论:stackoverflow.com/questions/56063136/…带来一些细节
  • 它是在“类型”请求的if 语句中定义的,您应该将其替换为<select> 的名称
  • 所以,除了测试相等性,我可以测试它是否存在?因为总是不明白为什么我应该测试相等性
  • 因为前端会将type发送到服务器。所以我可以用if($typeSlug = $request->get('type')){}代替if($rquest->has('type')){}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 2014-11-27
  • 1970-01-01
相关资源
最近更新 更多