php 在 Laravel 5 中使用表单请求验证时如何添加自定义验证规则

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28793716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:04:14  来源:igfitidea点击:

How add Custom Validation Rules when using Form Request Validation in Laravel 5

phplaravellaravel-5custom-validatorslaravel-validation

提问by gsk

I am using form request validation method for validating request in laravel 5.I would like to add my own validation rule with form request validation method.My request class is given below.I want to add custom validation numeric_array with field items.

我正在使用表单请求验证方法来验证 laravel 5 中的请求。我想使用表单请求验证方法添加我自己的验证规则。下面给出了我的请求类。我想添加带有字段项的自定义验证 numeric_array。

  protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array|numericarray']
];

My cusotom function is given below

我的自定义功能如下

 Validator::extend('numericarray', function($attribute, $value, $parameters) {
            foreach ($value as $v) {
                if (!is_int($v)) {
                    return false;
                }
            }
            return true;
        });

How can use this validation method with about form request validation in laravel5?

如何在 laravel5 中使用这种验证方法进行表单请求验证?

回答by lukasgeiter

Using Validator::extend()like you do is actually perfectly fine you just need to put that in a Service Providerlike this:

Validator::extend()像你一样使用实际上非常好,你只需要像这样把它放在一个服务提供者中

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ValidatorServiceProvider extends ServiceProvider {

    public function boot()
    {
        $this->app['validator']->extend('numericarray', function ($attribute, $value, $parameters)
        {
            foreach ($value as $v) {
                if (!is_int($v)) {
                    return false;
                }
            }
            return true;
        });
    }

    public function register()
    {
        //
    }
}

Then register the provider by adding it to the list in config/app.php:

然后通过将其添加到列表中来注册提供者config/app.php

'providers' => [
    // Other Service Providers

    'App\Providers\ValidatorServiceProvider',
],

You now can use the numericarrayvalidation rule everywhere you want

您现在可以在numericarray任何地方使用验证规则

回答by Adrian Gunawan

While the above answer is correct, in a lot of cases you might want to create a custom validation only for a certain form request. You can leverage laravel FormRequest and use dependency injection to extend the validation factory. I think this solution is much simpler than creating a service provider.

虽然上述答案是正确的,但在很多情况下,您可能只想为某个表单请求创建自定义验证。您可以利用 laravel FormRequest 并使用依赖注入来扩展验证工厂。我认为这个解决方案比创建服务提供商简单得多。

Here is how it can be done.

这是如何做到的。

use Illuminate\Validation\Factory as ValidationFactory;

class UpdateMyUserRequest extends FormRequest {

    public function __construct(ValidationFactory $validationFactory)
    {

        $validationFactory->extend(
            'foo',
            function ($attribute, $value, $parameters) {
                return 'foo' === $value;
            },
            'Sorry, it failed foo validation!'
        );

    }

    public function rules()
    {
        return [
            'username' => 'foo',
        ];
    }
}

回答by prograhammer

The accepted answer works for global validation rules, but many times you will be validating certain conditions that are very specific to a form. Here's what I recommend in those circumstances (that seems to be somewhat intended from Laravel source code at line 75 of FormRequest.php):

接受的答案适用于全局验证规则,但很多时候您将验证特定于表单的某些条件。这是我在这些情况下推荐的内容(这似乎有点来自 FormRequest.php 的第 75 行的Laravel 源代码):

Add a validator method to the parent Request your requests will extend:

将验证器方法添加到您的请求将扩展的父请求中:

<?php namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Validator;

abstract class Request extends FormRequest {

    public function validator(){

        $v = Validator::make($this->input(), $this->rules(), $this->messages(), $this->attributes());

        if(method_exists($this, 'moreValidation')){
            $this->moreValidation($v);
        }

        return $v;
    }
}

Now all your specific requests will look like this:

现在您的所有特定请求将如下所示:

<?php namespace App\Http\Requests;

use App\Http\Requests\Request;

class ShipRequest extends Request {

    public function rules()
    {
        return [
            'shipping_country' => 'max:60',
            'items' => 'array'
        ];
    }

    // Here we can do more with the validation instance...
    public function moreValidation($validator){

        // Use an "after validation hook" (see laravel docs)
        $validator->after(function($validator)
        {
            // Check to see if valid numeric array
            foreach ($this->input('items') as $item) {
                if (!is_int($item)) {
                    $validator->errors()->add('items', 'Items should all be numeric');
                    break;
                }
            }
        });
    }

    // Bonus: I also like to take care of any custom messages here
    public function messages(){
        return [
            'shipping_country.max' => 'Whoa! Easy there on shipping char. count!'
        ];
    }
}

回答by gk.

Custom Rule Object

自定义规则对象

One way to do it is by using Custom Rule Object, this way you can define as many rule as you want without need to make changes in Providers and in controller/service to set new rules.

一种方法是使用Custom Rule Object,这样您就可以定义任意数量的规则,而无需在 Providers 和控制器/服务中进行更改以设置新规则。

php artisan make:rule NumericArray

In NumericArray.php

在 NumericArray.php 中

namespace App\Rules;
class NumericArray implements Rule
{
   public function passes($attribute, $value)
   {
     foreach ($value as $v) {
       if (!is_int($v)) {
         return false;
       }
     }
     return true;
   }


  public function message()
  {
     return 'error message...';
  }
}

Then in Form request have

然后在表单请求中有

use App\Rules\NumericArray;
.
.
protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array', new NumericArray]
];

回答by Marcin Nabia?ek

You need to override getValidatorInstancemethod in your Requestclass, for example this way:

你需要getValidatorInstance在你的Request类中重写方法,例如这样:

protected function getValidatorInstance()
{
    $validator = parent::getValidatorInstance();
    $validator->addImplicitExtension('numericarray', function($attribute, $value, $parameters) {
        foreach ($value as $v) {
            if (!is_int($v)) {
                return false;
            }
        }
        return true;
    });

    return $validator;
}

回答by vguerrero

Alternatively to Adrian Gunawan's solutionthis now also can be approached like:

替代Adrian Gunawan 的解决方案,现在也可以这样处理:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreBlogPost extends FormRequest
{
    public function rules()
    {
        return [
            'title' => ['required', 'not_lorem_ipsum'],
        ];
    }

    public function withValidator($validator)
    {
        $validator->addExtension('not_lorem_ipsum', function ($attribute, $value, $parameters, $validator) {
            return $value != 'lorem ipsum';
        });

        $validator->addReplacer('not_lorem_ipsum', function ($message, $attribute, $rule, $parameters, $validator) {
            return __("The :attribute can't be lorem ipsum.", compact('attribute'));
        });
    }
}

回答by Félix Díaz

You don't need to extend the validator to validate array items, you can validate each item of a array with "*" as you can see in Array Validation

您不需要扩展验证器来验证数组项,您可以使用“*”验证数组的每个项,如数组验证中所见

protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array'],
      'items.*' => 'integer'
];

回答by Carolina

For me works the solution that give us lukasgeiter, but with a difference that we create a class with our custom validations ,like this, for laravel 5.2.* The next example is for add a validation to a range of date in where the second date has to be equals or more big that the first one

对我来说,解决方案为我们提供了 lukasgeiter,但不同的是,我们使用自定义验证创建了一个类,就像这样,对于 laravel 5.2。* 下一个示例是将验证添加到第二个日期的日期范围必须等于或大于第一个

In app/Providers create ValidatorExtended.php

在 app/Providers 创建 ValidatorExtended.php

<?php
namespace App\Providers;
use Illuminate\Validation\Validator as IlluminateValidator;

class ValidatorExtended extends IlluminateValidator {

private $_custom_messages = array(
 "after_or_equal" => ":attribute debe ser una fecha posterior o igual a 
 :date.",
);

public function __construct( $translator, $data, $rules, $messages = array(),      
$customAttributes = array() ) {
  parent::__construct( $translator, $data, $rules, $messages, 
  $customAttributes );
  $this->_set_custom_stuff();
}

protected function _set_custom_stuff() {
   //setup our custom error messages
  $this->setCustomMessages( $this->_custom_messages );
}

/**
 * La fecha final debe ser mayor o igual a la fecha inicial
 *
 * after_or_equal
 */
protected function validateAfterOrEqual( $attribute, $value, $parameters, 
$validator) {
   return strtotime($validator->getData()[$parameters[0]]) <= 
  strtotime($value);
}

}   //end of class

Ok. now lets create the Service Provider. Create ValidationExtensionServiceProvider.php inside app/Providers, and we code

好的。现在让我们创建服务提供者。在 app/Providers 里面创建 ValidationExtensionServiceProvider.php,然后我们编码

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Validator;

class ValidationExtensionServiceProvider extends ServiceProvider {

public function register() {}

public function boot() {
  $this->app->validator->resolver( function( $translator, $data, $rules, 
  $messages = array(), $customAttributes = array() ) {
    return new ValidatorExtended( $translator, $data, $rules, $messages, 
    $customAttributes );
} );
}

}   //end of class

Now we to tell Laravel to load this Service Provider, add to providers array at the end in config/app.php and

现在我们告诉 Laravel 加载这个服务提供者,在 config/app.php 的最后添加到 providers 数组和

//Servicio para extender validaciones
App\Providers\ValidationExtensionServiceProvider::class,

now we can use this validation in our request in function rules

现在我们可以在函数规则中的请求中使用此验证

public function rules()
{
  return [
    'fDesde'     => 'date',
    'fHasta'     => 'date|after_or_equal:fDesde'
 ];
}

or in Validator:make

或在 Validator:make

$validator = Validator::make($request->all(), [
    'fDesde'     => 'date',
    'fHasta'     => 'date|after_or_equal:fDesde'
], $messages);

you have to notice that the name of the method that makes the validation has the prefix validate and is in camel case style validateAfterOrEqual but when you use the rule of validation every capital letter is replaced with underscore and the letter in lowercase letter.

您必须注意到进行验证的方法的名称具有前缀 validate 并且采用驼峰式大小写样式 validateAfterOrEqual 但是当您使用验证规则时,每个大写字母都被替换为下划线和小写字母。

All this I take it from https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators//here explain in details. thanks to them.

所有这些我都从https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators//这里详细解释。感谢他们。

回答by Nole

All answers on this page will solve you the problem, but... But the only right way by the Laravel conventions is solution from Ganesh Karki

此页面上的所有答案都可以解决您的问题,但是...但是 Laravel 约定的唯一正确方法是Ganesh Karki 的解决方案

One example:

一个例子:

Let's take an example of a form to fill in Summer Olympic Games events – so year and city. First create one form.

让我们以填写夏季奥运会赛事的表格为例 - 所以年份和城市。首先创建一个表单。

<form action="/olimpicyear" method="post">
  Year:<br>
  <input type="text" name="year" value=""><br>
  City:<br>
  <input type="text" name="city" value=""><br><br>
  <input type="submit" value="Submit">
</form> 

Now, let's create a validation rule that you can enter only the year of Olympic Games. These are the conditions

现在,让我们创建一个验证规则,您只能输入奥运会的年份。这些是条件

  1. Games started in 1896
  2. Year can't be bigger than current year
  3. Number should be divided by 4
  1. 比赛始于 1896 年
  2. 年份不能大于当前年份
  3. 数字应除以 4

Let's run a command:

让我们运行一个命令:

php artisan make:rule OlympicYear

php artisan make:rule OlympicYear

Laravel generates a file app/Rules/OlympicYear.php. Change that file to look like this:

Laravel 生成一个文件app/Rules/OlympicYear.php。将该文件更改为如下所示:

namespace App\Rules;

命名空间 App\Rules;

use Illuminate\Contracts\Validation\Rule;

使用 Illuminate\Contracts\Validation\Rule;

class OlympicYear implements Rule {

类 OlympicYear 实现规则 {

/**
 * Determine if the validation rule passes.
 *
 * @param  string  $attribute
 * @param  mixed  $value
 * @return bool
 */
public function passes($attribute, $value)
{
    // Set condition that should be filled
    return $value >= 1896 && $value <= date('Y') && $value % 4 == 0;
}

/**
 * Get the validation error message.
 *
 * @return string
 */
public function message()
{
    // Set custom error message.
    return ':attribute should be a year of Olympic Games';
}

}

}

Finally, how we use this class? In controller's store() method we have this code:

最后,我们如何使用这个类?在控制器的 store() 方法中,我们有以下代码:

public function store(Request $request)
{
    $this->validate($request, ['year' => new OlympicYear]);
}

If you want to create validation by Laravel conventions follow tutorial in link below. It is easy and very well explained. It helped me a lot. Link for original tutorial is here Tutorial link.

如果您想通过 Laravel 约定创建验证,请按照下面链接中的教程进行操作。这很容易,而且解释得很好。这对我帮助很大。原始教程的链接在这里教程链接