laravel 自定义验证
In the previous part we learned how to validate data in Laravel using its in-built data validation package and how to abstract out our data validation to entity specific services to make the code reusable on the principles of DRY. Now, we can easily create a validation service for each entity in our app with its own respective validation rules, inject it wherever we want to validate data and easily fetch and display errors etc.
在上一部分中,我们学习了如何使用Laravel的内置数据验证包在Laravel中验证数据,以及如何将数据验证抽象到特定于实体的服务,以使代码根据DRY原则可重用。 现在,我们可以使用自己的验证规则轻松地为应用程序中的每个实体创建一个验证服务,将其注入我们想要验证数据的任何位置,并轻松获取和显示错误等。
But what if we want more?
但是,如果我们想要更多呢?
The source code for this tutorial is available here. You just need to run
composer install
to install the Laravel framework inside the project directory before you are able to run this code.本教程的源代码在此处 。 您只需要运行
composer install
即可在项目目录中安装Laravel框架,然后才能运行此代码。
需要更多 (The Need for More)
Out of the box, Laravel provides many useful and generic validation rules. But what if we want more? What if we need something more specific? In our example here, in TestFormValidator
we have used alpha_dash
to validate Names but that is not ideal to validate a full name. Generally, a person’s full name would consist of a First Name and a Last Name and maybe a Middle Name as well. All these would be separated by a space. Similarly if we want to validate the Pin Code in our form we cannot use alpha_num
rule provided by Laravel, we should be able to allow spaces in it as well.
开箱即用,Laravel提供了许多有用的通用验证规则。 但是,如果我们想要更多呢? 如果我们需要更具体的内容怎么办? 在此处的示例中,在TestFormValidator
我们使用alpha_dash
来验证名称,但是验证全名并不理想。 通常,一个人的全名将由一个名字和一个姓氏以及中间名组成。 所有这些都将以空格分隔。 类似地,如果我们要以我们的形式验证Pin Code,则不能使用alpha_num
提供的alpha_num规则,我们也应该能够在其中保留空格。
Well, Laravel provides the option to easily extend its validation package and add custom validation rules to it. In RocketCandy/Services/Validation/
create ValidatorExtended.php
and add the following code to it:
好吧,Laravel提供了轻松扩展其验证包并为其添加自定义验证规则的选项。 在RocketCandy/Services/Validation/
创建ValidatorExtended.php
并向其中添加以下代码:
<?php
namespace RocketCandy\Services\Validation;
use Illuminate\Validation\Validator as IlluminateValidator;
class ValidatorExtended extends IlluminateValidator {
private $_custom_messages = array(
"alpha_dash_spaces" => "The :attribute may only contain letters, spaces, and dashes.",
"alpha_num_spaces" => "The :attribute may only contain letters, numbers, and spaces.",
);
public function __construct( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) {
parent::__construct( $translator, $data, $rules, $messages, $customAttributes );
$this->_set_custom_stuff();
}
/**
* Setup any customizations etc
*
* @return void
*/
protected function _set_custom_stuff() {
//setup our custom error messages
$this->setCustomMessages( $this->_custom_messages );
}
/**
* Allow only alphabets, spaces and dashes (hyphens and underscores)
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
protected function validateAlphaDashSpaces( $attribute, $value ) {
return (bool) preg_match( "/^[A-Za-z\s-_]+$/", $value );
}
/**
* Allow only alphabets, numbers, and spaces
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
protected function validateAlphaNumSpaces( $attribute, $value ) {
return (bool) preg_match( "/^[A-Za-z0-9\s]+$/", $value );
}
} //end of class
//EOF
Here our class extends Laravel’s Illuminate\Validation\Validator
class and adds two new methods (validateAlphaDashSpaces()
and validateAlphaNumSpaces()
) to validate data and their respective error messages with the placeholder :attribute
in them which Laravel would replace at runtime with the name of whichever data field that is being validated.
在这里,我们的类扩展了Laravel的Illuminate\Validation\Validator
类,并添加了两个新方法( validateAlphaDashSpaces()
和validateAlphaNumSpaces()
)以使用占位符来验证数据及其各自的错误消息:attribute
在运行时Laravel将使用名称替换其:attribute
为验证中的任何数据字段。
Now the thing to note here is how we name the methods. All validation rule method names must have the validate
prefix and the rest of it must be in Title Case (without spaces, of course). The validation rule will be in lowercase of what the method is named (without validation
prefix) and each word will be separated by an underscore. So if we want to add an alpha_dash_spaces
validation rule then our corresponding method will be named validateAlphaDashSpaces()
.
现在要注意的是我们如何命名方法。 所有验证规则方法名称都必须具有validate
前缀,其余名称必须在Title Case中(当然不能有空格)。 验证规则将以小写形式表示该方法的名称(不带validation
前缀),并且每个单词将由下划线分隔。 因此,如果我们要添加alpha_dash_spaces
验证规则,则我们的相应方法将命名为validateAlphaDashSpaces()
。
So we have added alpha_dash_spaces
and alpha_num_spaces
validation rules here. alpha_dash_spaces
will allow letters, dashes (hyphens and underscores) and spaces while alpha_num_spaces
will allow only letters, numbers (numbers 0-9) and spaces.
因此,我们在此处添加了alpha_dash_spaces
和alpha_num_spaces
验证规则。 alpha_dash_spaces
将允许使用字母,破折号(连字符和下划线)和空格,而alpha_num_spaces
将仅允许使用字母,数字(数字0至9)和空格。
We are not done with this just yet, this class only extends Laravel’s validation class. We still have to make Laravel recognize it so that when we add the new rules to our vaidation service above, Laravel would know how to run the validation as per those rules.
我们还没有完成此工作,该类仅扩展了Laravel的验证类。 我们仍然必须让Laravel识别它,以便在将新规则添加到上面的验证服务中时,Laravel会知道如何根据这些规则运行验证。
Laravel docs state that we can do this:
Laravel文档指出我们可以做到这一点:
Validator::resolver( function( $translator, $data, $rules, $messages ) {
return new \RocketCandy\Services\Validation\ValidatorExtended( $translator, $data, $rules, $messages );
} );
and stick it in app/start/global.php
or maybe create a new file inside app
directory and load that file in app/start/global.php
. But that does not look so clean, modifying files we don’t need to modify, sticking bits and pieces here and there. No, we would rather keep all this validation related code together, so we are going to create a Service Provider and glue our custom validation rules into Laravel’s validation package there.
并将其粘贴在app/start/global.php
或者在app
目录中创建一个新文件,然后将该文件加载到app/start/global.php
。 但这看起来并不干净,可以修改我们不需要修改的文件,零零散散。 不,我们宁愿将所有与验证相关的代码放在一起,因此我们将创建一个服务提供程序,并将我们的自定义验证规则粘贴到Laravel的验证包中。
Create ValidationExtensionServiceProvider.php
inside RocketCandy/Services/Validation/
and add the following code to it:
在RocketCandy/Services/Validation/
创建ValidationExtensionServiceProvider.php
, RocketCandy/Services/Validation/
添加以下代码:
<?php
namespace RocketCandy\Services\Validation;
use Illuminate\Support\ServiceProvider;
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
//EOF
If you have created a Service Provider in Laravel before you would usually have used register()
method to do whatever binding you needed. It is the only abstract
method in the abstract class Illuminate\Support\ServiceProvider
that we have extended here. The reason we cannot glue our validation extension in register()
is that it is fired as soon as the Service Provider is loaded by Laravel and we would run into a volley of exceptions thrown at us as Laravel initializes its validation package later, so we would be trying to extend stuff that is not there using an object which does not exist. The boot()
method on the other hand is fired just before a request is routed, so we can safely glue our stuff to Laravel’s validation package there.
如果您之前通常在Laravel中创建了Service Provider,则通常会使用register()
方法来完成所需的绑定。 这是我们在此处扩展的抽象类Illuminate\Support\ServiceProvider
中的唯一abstract
方法。 我们无法将验证扩展粘贴到register()
是,一旦Laravel加载了服务提供商,就会触发它,并且在Laravel初始化其验证包时,我们会遇到大量异常。正在尝试使用不存在的对象扩展不存在的内容。 另一方面, boot()
方法在路由请求之前被触发,因此我们可以安全地将东西粘贴到Laravel的验证包中。
Now we just need to tell Laravel to load this Service Provider and we would be all set. Open up your app/config/app.php
and in the providers
array add the following at the end:
现在,我们只需要告诉Laravel加载该服务提供者,我们就可以准备就绪。 打开您的app/config/app.php
然后在providers
数组末尾添加以下内容:
'RocketCandy\Services\Validation\ValidationExtensionServiceProvider',
Now, open app/RocketCandy/Services/Validation/TestFormValidator.php
and update the $rules
property so it would look like this:
现在,打开app/RocketCandy/Services/Validation/TestFormValidator.php
并更新$rules
属性,如下所示:
public $rules = array(
'name' => array( 'required', 'alpha_dash_spaces', 'max:200' ),
'email' => array( 'required', 'email', 'min:6', 'max:200' ),
'phone' => array( 'required', 'numeric', 'digits_between:8,25' ),
'pin_code' => array( 'required', 'alpha_num_spaces', 'max:25' ),
);
We replaced the alpha_dash
validation rule for name
with alpha_dash_spaces
and alpha_num
for pin_code
with alpha_num_spaces
.
我们将name
的alpha_dash
验证规则替换为alpha_dash_spaces
,将alpha_num
的pin_code
为alpha_num_spaces
。
Now if we navigate to http://<your-project-domain>/dummy/create
we can enter spaces in the Name and Pin Code fields without any issues and the data will pass validation on submit.
现在,如果我们导航到http://<your-project-domain>/dummy/create
则可以在“名称”和“密码”字段中输入空格,而不会出现任何问题,并且数据将在提交时通过验证。
摘要 (Summary)
So in this two part tutorial we learned to:
因此,在这两部分的教程中,我们学习了:
- Validate data in Laravel using its built in data validation package. 使用其内置的数据验证包在Laravel中验证数据。
Use the Object Oriented approach to abstract out data validation to it’s own separate service (Single Responsibility achievement unlocked).
使用面向对象的方法将数据验证抽象到它自己的单独服务中( 单一职责实现已解锁)。
Create our own custom exceptions to use with our data validation service (instead of using
TRUE/FALSE
boolean values) and how to store and retrieve errors from them.创建我们自己的自定义异常,以与我们的数据验证服务一起使用(而不是使用
TRUE/FALSE
布尔值),以及如何存储和从中检索错误。- Inject our data validation service in our Controller and use it. 将我们的数据验证服务注入我们的Controller中并使用它。
- Extend Laravel’s validation package with our custom validation rules and auto-load it using a Service Provider. 使用我们的自定义验证规则扩展Laravel的验证包,并使用服务提供商自动加载它。
脚注 (Footnotes)
For the sake of keeping this tutorial to the point I injected the validation service in our Controller and used it there. In a real-life project you would most likely use the validation service somewhere else where you would handle data sanitization and storage. Ideally, Controllers should be fat free and have the bare minimum of code.
为了使本教程讲究重点,我将验证服务注入了Controller并在其中使用了它。 在现实生活中的项目中,您很可能会在其他要处理数据清理和存储的地方使用验证服务。 理想情况下,控制器应该是无脂肪的,并且几乎没有代码。
Got thoughts? Questions? Fire away in the comments.
有想法吗? 有什么问题吗 在评论中开除。
翻译自: https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators/
laravel 自定义验证