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

时间:2021-12-07 07:11:15

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

我的cusotom功能如下

 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中使用此验证方法进行表单请求验证?

7 个解决方案

#1


38  

Using Validator::extend() like you do is actually perfectly fine you just need to put that in a Service Provider like 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 numericarray validation rule everywhere you want

您现在可以在任何位置使用数字阵列验证规则

#2


31  

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',
        ];
    }
}

#3


19  

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!'
        ];
    }
}

#4


5  

You need to override getValidatorInstance method in your Request class, for example this way:

您需要在Request类中覆盖getValidatorInstance方法,例如这样:

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;
}

#5


3  

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'
];

#6


0  

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并且采用camel case样式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//这里详细解释的。谢谢他们。

#7


0  

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.

一种方法是使用自定义规则对象,这样您就可以根据需要定义任意数量的规则,而无需在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

然后在Form请求中

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

#1


38  

Using Validator::extend() like you do is actually perfectly fine you just need to put that in a Service Provider like 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 numericarray validation rule everywhere you want

您现在可以在任何位置使用数字阵列验证规则

#2


31  

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',
        ];
    }
}

#3


19  

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!'
        ];
    }
}

#4


5  

You need to override getValidatorInstance method in your Request class, for example this way:

您需要在Request类中覆盖getValidatorInstance方法,例如这样:

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;
}

#5


3  

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'
];

#6


0  

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并且采用camel case样式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//这里详细解释的。谢谢他们。

#7


0  

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.

一种方法是使用自定义规则对象,这样您就可以根据需要定义任意数量的规则,而无需在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

然后在Form请求中

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