在 Laravel 5 中使用表单请求验证时如何添加自定义验证规则
How add Custom Validation Rules when using Form Request Validation in Laravel 5
我正在使用表单请求验证方法来验证 laravel 中的请求 5.I 想添加我自己的表单请求验证规则 method.My 请求 class 是给定 below.I 想要添加带有字段项的自定义验证 numeric_array。
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array|numericarray']
];
我的自定义函数如下
Validator::extend('numericarray', function($attribute, $value, $parameters) {
foreach ($value as $v) {
if (!is_int($v)) {
return false;
}
}
return true;
});
如何将此验证方法与 laravel5 中的表单请求验证一起使用?
您需要覆盖 Request
class 中的 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;
}
像你一样使用 Validator::extend()
实际上非常好,你只需要像这样把它放在 Service Provider 中:
<?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()
{
//
}
}
然后通过将提供商添加到 config/app.php
中的列表来注册提供商:
'providers' => [
// Other Service Providers
'App\Providers\ValidatorServiceProvider',
],
您现在可以在任何地方使用 numericarray
验证规则
已接受的答案适用于全局验证规则,但很多时候您将验证特定于表单的某些条件。这是我在这些情况下的建议(这似乎有点来自 line 75 of FormRequest.php 的 Laravel 源代码):
向父请求添加验证器方法,您的请求将扩展:
<?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;
}
}
现在您的所有具体请求将如下所示:
<?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!'
];
}
}
虽然上面的答案是正确的,但在很多情况下,您可能只想为特定的表单请求创建自定义验证。您可以利用 laravel FormRequest 并使用依赖注入来扩展验证工厂。我认为这个解决方案比创建服务提供者要简单得多。
这是如何完成的。
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',
];
}
}
您不需要扩展验证器来验证数组项,您可以使用“*”验证数组的每个项,如您在
Array Validation
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array'],
'items.*' => 'integer'
];
对我来说,解决方案给了我们 lukasgeiter,但不同之处在于我们使用我们的自定义验证创建了一个 class,就像这样,用于 laravel 5.2。*下一个示例用于添加对日期范围的验证,其中第二个日期必须等于或大于第一个
在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
好的。现在让我们创建服务提供者。在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
现在我们告诉 Laravel 加载这个服务提供者,添加到 config/app.php 和
中最后的提供者数组
//Servicio para extender validaciones
App\Providers\ValidationExtensionServiceProvider::class,
现在我们可以在函数规则的请求中使用此验证
public function rules()
{
return [
'fDesde' => 'date',
'fHasta' => 'date|after_or_equal:fDesde'
];
}
或 Validator:make
$validator = Validator::make($request->all(), [
'fDesde' => 'date',
'fHasta' => 'date|after_or_equal:fDesde'
], $messages);
你必须注意,使验证的方法的名称具有前缀 validate 并且是驼峰式风格 validateAfterOrEqual 但是当你使用验证规则时,每个大写字母都被替换为下划线和小写字母字母.
这一切我从https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators//这里得到详细解释。感谢他们。
自定义规则对象
一种方法是使用 Custom Rule Object,这样您可以根据需要定义任意数量的规则,而无需在提供程序和 controller/service 中进行更改以设置新规则。
php artisan make:rule NumericArray
在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...';
}
}
然后在Form请求中有
use App\Rules\NumericArray;
.
.
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array', new NumericArray]
];
此页面上的所有答案都会解决您的问题,但是...但是 Laravel 约定的唯一正确方法是 Ganesh Karki
的解决方案
一个例子:
让我们以填写夏季奥运会赛事的表格为例——年份和城市。先创建一个表格。
<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>
现在,让我们创建一个只能输入奥运会年份的验证规则。这些是条件
- 1896 年开始的比赛
- 年份不能大于当前年份
- 数字应除以 4
让我们运行一个命令:
php artisan make:rule 奥林匹克年
Laravel 生成文件 app/Rules/OlympicYear.php。将该文件更改为如下所示:
命名空间App\Rules;
使用Illuminate\Contracts\Validation\Rule;
class 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';
}
}
最后,我们如何使用这个class?在控制器的 store() 方法中,我们有这样的代码:
public function store(Request $request)
{
$this->validate($request, ['year' => new OlympicYear]);
}
如果您想按照 Laravel 约定创建验证,请按照下面 link 中的教程进行操作。这很容易,而且解释得很好。这对我帮助很大。 Link 原始教程在这里 Tutorial link。
或者 现在也可以这样处理:
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'));
});
}
}
我正在使用表单请求验证方法来验证 laravel 中的请求 5.I 想添加我自己的表单请求验证规则 method.My 请求 class 是给定 below.I 想要添加带有字段项的自定义验证 numeric_array。
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array|numericarray']
];
我的自定义函数如下
Validator::extend('numericarray', function($attribute, $value, $parameters) {
foreach ($value as $v) {
if (!is_int($v)) {
return false;
}
}
return true;
});
如何将此验证方法与 laravel5 中的表单请求验证一起使用?
您需要覆盖 Request
class 中的 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;
}
像你一样使用 Validator::extend()
实际上非常好,你只需要像这样把它放在 Service Provider 中:
<?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()
{
//
}
}
然后通过将提供商添加到 config/app.php
中的列表来注册提供商:
'providers' => [
// Other Service Providers
'App\Providers\ValidatorServiceProvider',
],
您现在可以在任何地方使用 numericarray
验证规则
已接受的答案适用于全局验证规则,但很多时候您将验证特定于表单的某些条件。这是我在这些情况下的建议(这似乎有点来自 line 75 of FormRequest.php 的 Laravel 源代码):
向父请求添加验证器方法,您的请求将扩展:
<?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;
}
}
现在您的所有具体请求将如下所示:
<?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!'
];
}
}
虽然上面的答案是正确的,但在很多情况下,您可能只想为特定的表单请求创建自定义验证。您可以利用 laravel FormRequest 并使用依赖注入来扩展验证工厂。我认为这个解决方案比创建服务提供者要简单得多。
这是如何完成的。
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',
];
}
}
您不需要扩展验证器来验证数组项,您可以使用“*”验证数组的每个项,如您在 Array Validation
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array'],
'items.*' => 'integer'
];
对我来说,解决方案给了我们 lukasgeiter,但不同之处在于我们使用我们的自定义验证创建了一个 class,就像这样,用于 laravel 5.2。*下一个示例用于添加对日期范围的验证,其中第二个日期必须等于或大于第一个
在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
好的。现在让我们创建服务提供者。在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
现在我们告诉 Laravel 加载这个服务提供者,添加到 config/app.php 和
中最后的提供者数组//Servicio para extender validaciones
App\Providers\ValidationExtensionServiceProvider::class,
现在我们可以在函数规则的请求中使用此验证
public function rules()
{
return [
'fDesde' => 'date',
'fHasta' => 'date|after_or_equal:fDesde'
];
}
或 Validator:make
$validator = Validator::make($request->all(), [
'fDesde' => 'date',
'fHasta' => 'date|after_or_equal:fDesde'
], $messages);
你必须注意,使验证的方法的名称具有前缀 validate 并且是驼峰式风格 validateAfterOrEqual 但是当你使用验证规则时,每个大写字母都被替换为下划线和小写字母字母.
这一切我从https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators//这里得到详细解释。感谢他们。
自定义规则对象
一种方法是使用 Custom Rule Object,这样您可以根据需要定义任意数量的规则,而无需在提供程序和 controller/service 中进行更改以设置新规则。
php artisan make:rule NumericArray
在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...';
}
}
然后在Form请求中有
use App\Rules\NumericArray;
.
.
protected $rules = [
'shipping_country' => ['max:60'],
'items' => ['array', new NumericArray]
];
此页面上的所有答案都会解决您的问题,但是...但是 Laravel 约定的唯一正确方法是 Ganesh Karki
的解决方案一个例子:
让我们以填写夏季奥运会赛事的表格为例——年份和城市。先创建一个表格。
<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>
现在,让我们创建一个只能输入奥运会年份的验证规则。这些是条件
- 1896 年开始的比赛
- 年份不能大于当前年份
- 数字应除以 4
让我们运行一个命令:
php artisan make:rule 奥林匹克年
Laravel 生成文件 app/Rules/OlympicYear.php。将该文件更改为如下所示:
命名空间App\Rules;
使用Illuminate\Contracts\Validation\Rule;
class 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';
}
}
最后,我们如何使用这个class?在控制器的 store() 方法中,我们有这样的代码:
public function store(Request $request)
{
$this->validate($request, ['year' => new OlympicYear]);
}
如果您想按照 Laravel 约定创建验证,请按照下面 link 中的教程进行操作。这很容易,而且解释得很好。这对我帮助很大。 Link 原始教程在这里 Tutorial link。
或者
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'));
});
}
}