Laravel 5.5 无法在表单请求类中制作验证器

Posted

技术标签:

【中文标题】Laravel 5.5 无法在表单请求类中制作验证器【英文标题】:Laravel 5.5 cannot make validator in a form Request class 【发布时间】:2018-07-13 18:59:33 【问题描述】:

我想检查是否仅当两个“villes”具有相同名称时才填写表单输入“departement”。

在控制器内,这段代码完美地工作:

 $rules=[  'nom' => 'required', 'ville'=> 'required|exists:villes,nom'];
 $messages = [
      'depart.required' => 'Deux villes portent le même nom, preciser le 
 département'];
  $validator = Validator::make($request->All(), $rules,$messages);
  $validator->sometimes('depart_id', 'required|exists:departs,id', function 
  ($input) 
      return Ville::where('nom',$input->ville)->count()>1;
  );
  if ($validator->fails()) 
    return redirect('admin/etab/create')
            ->withErrors($validator)
            ->withInput();
    

我将相同的代码放在表单请求类中:

public function rules()

  $rules=[  'nom' => 'required', 'ville'=> 'required|exists:villes,nom'];
  $messages = [
      'depart.required' => 'Deux villes portent le même nom, preciser le 
  département',
  ];
  $validator = Validator::make($this->All(), $rules,$messages);
  $validator->sometimes('depart_id', 'required|exists:departs,id', function 
  ($input) 
      return Ville::where('nom',$input->ville)->count()>1;
  );
  return $validator;

我收到"Type error: Argument 2 passed to Illuminate\Validation\Factory::make() must be of the type array, object given," 我认为错误消息不充分,但我找不到为什么这种方式不起作用

谢谢......

【问题讨论】:

不要覆盖框架类,只是,不要。查看laravel.com/docs/5.5/validation#form-request-validation FormRequest 类中的 rules 方法应该返回一个数组,而不是一个 Validator 对象。这就是您在此处看到的错误。 @Robert 我知道规则不是我的代码的好地方,但我找不到 int 文档应该在 FormRequest 中的哪个位置放置我的代码... @aprokryfos 抱歉,我没有重写框架请求类,我创建了一个 FormRequest 类。 (我编辑了帖子) 【参考方案1】:

您可以查看vendor/laravel/framework/src/Illuminate/Foundation/Http/FormRequest.php 中的FormRequest 类并查看它的作用。

它在顶部包含这两个方法:

/**
 * Get the validator instance for the request.
 *
 * @return \Illuminate\Contracts\Validation\Validator
 */
protected function getValidatorInstance()

    $factory = $this->container->make(ValidationFactory::class);

    if (method_exists($this, 'validator')) 
        $validator = $this->container->call([$this, 'validator'], compact('factory'));
     else 
        $validator = $this->createDefaultValidator($factory);
    

    if (method_exists($this, 'withValidator')) 
        $this->withValidator($validator);
    

    return $validator;


/**
 * Create the default validator instance.
 *
 * @param  \Illuminate\Contracts\Validation\Factory  $factory
 * @return \Illuminate\Contracts\Validation\Validator
 */
protected function createDefaultValidator(ValidationFactory $factory)

    return $factory->make(
        $this->validationData(), $this->container->call([$this, 'rules']),
        $this->messages(), $this->attributes()
    );

所以你基本上可以在你自己的 FormRequest 类中提供一个validator 方法来创建一个自定义的 Validator 对象,该方法将 ValidatorFactory 作为参数。

在您的情况下,您不需要这样做,因为您只想将 sometimes 规则附加到默认验证器。看上面的代码,它检查withValidator方法是否存在,如果存在则调用:

    if (method_exists($this, 'withValidator')) 
        $this->withValidator($validator);
    

您可以创建 FormRequest,确保正确使用 rulesmessagesauthorize 方法,例如规则和消息返回数组,授权返回布尔值。

然后创建一个withValidator 方法,在该方法中将有时规则附加到验证器。

/**
 * Do foo with Validator
 *
 * @param \Illuminate\Contracts\Validation\Validator $validator
 * @return void
 */
public function withValidator(Validator $validator)

    $validator->sometimes('depart_id', 'required|exists:departs,id', function 
        return Ville::where('nom', $this->input('ville'))->count() > 1;
    );

这样sometimes 在执行验证之前会附加到您的验证器。

【讨论】:

【参考方案2】:

您不会将所有验证逻辑都放在这样的规则方法中。只有规则定义在那里。你只需要这个:

public function rules()

  return [
    'nom' => 'required', 
    'ville'=> 'required|exists:villes,nom',
  ];

Laravel 将从那里开始处理验证。使用FormRequests时无需手动创建Validator类。

自定义消息涉及在类中创建messages 方法,如下所示:

public function messages()

    return [
        'depart.required' => 'Deux villes portent le même nom, preciser le départemen'
    ];

更新

至于sometimes 规则,我建议创建一个Rule 对象并自定义您需要如何检查2 个同名的别墅。

Rule classes

【讨论】:

检查 ville 是否存在就可以了。但我想检查部门是否仅存在于两个别墅具有相同名称的情况下。为此,我需要一个 sometmes 规则.... 好的,但我发布的是 FormRequest 类需要如何布局。在rules 方法中拥有验证器实例和消息数组的方式是错误的。需要删除这些才能使 FormRequest 类正常工作

以上是关于Laravel 5.5 无法在表单请求类中制作验证器的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.5 - 同时验证多个表单请求

Laravel 5.5 FormRequest 自定义表单请求验证类

Laravel 5.5 / 验证器 / 自定义规则

laravel 5.5 修改注册表单验证规则

Laravel 5.5 无法使用身份验证脚手架登录

Laravel 5.5 的自定义验证对象/类