今天来讲一下,Lumen的Validator函数
1
2
3
4
5
6
7
8
9
10
11
|
use
Validator;
...
Class .. {
public
function
..(){
Validator::make(
$input
,
$rules
,
$message
,
$attributes
)->validate();
}
|
1
|
use
Validator是可以直接引用的,虽然不能直接找到该命名空间的对应的位置。也可以直接在控制器
use
和使用Validator::make()。
|
1
|
<em>至于类名和函数名就随意啦,
$input
为传入验证的数组,
$rule
为验证规则,
$message
为返回的规则,</em>
$attributes
为验证字段的对应中文注释。废话少说,先模拟一个标准的数据,
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
$input
= [
'typeid'
=> 1,
'title'
=>
'测试标题'
,
'content'
=>
'测试内容'
];
$rules
= [
'typeid'
=>
'required|numeric'
,
'title'
=>
'required'
,
'content'
=>
'required'
];
$message
= [
"required"
=>
":attribute 不能为空"
,
"numeric"
=>
":attribute 格式不正确"
];
$attributes
= [
'typeid'
=>
'分类id'
,
'title'
=>
'标题'
,
'content'
=>
'内容'
];
|
执行后,可能报错Illuminate\Validation\ValidationException: The given data failed to pass validation ...... vendor\illuminate\validation\Validator.php on line305
这是Lumen的异常处理机制,vendor\illuminate\validation\Validator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
function
validate()
{
if
(
$this
->fails()) {
throw
new
ValidationException(
$this
);
}
}
|
看看vendor\illuminate\validation\ValidationException.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
ValidationException
extends
Exception
{
...
public
function
__construct(
$validator
,
$response
= null)
{
parent::__construct(
'The given data failed to pass validation.'
);
$this
->response =
$response
;
$this
->validator =
$validator
;
}
|
直接这样抛出异常肯定不ok,接下看看解决方法,
方法一,异常拦截
进入app\Exceptions\Hanlder.php
1
2
3
4
5
6
7
8
9
|
public
function
render(
$request
, Exception
$e
)
{
if
(
$e
instanceof
\Illuminate\Validation\ValidationException) {
return
$this
->handleValidationException(
$request
,
$e
);
}
return
parent::render(
$request
,
$e
);
}<br data-filtered=
"filtered"
><br data-filtered=
"filtered"
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
protected
function
handleValidationException(
$request
,
$e
)
{
$errors
= @
$e
->validator->errors()->toArray();
$message
= null;
if
(
count
(
$errors
)) {
$firstKey
=
array_keys
(
$errors
)[0];
$message
= @
$e
->validator->errors()->get(
$firstKey
)[0];
if
(
strlen
(
$message
) == 0) {
$message
=
"An error has occurred when trying to register"
;
}
}
if
(
$message
== null) {
$message
=
"An unknown error has occured"
;
}
return
$message
;
}
|
结果会返回第一个验证不过的对应信息。
不过直接在异常这里做处理不太合理,方法二
1
2
3
4
5
6
7
8
|
$validator
= Validator::make(
$input
,
$rules
,
$message
,
$attributes
);
$failed
=
$validator
->failed();
$messages
=
$validator
->messages();
if
(
count
(
$messages
) != 0){
dataReturn(1,current(current(
$messages
))[0]);
}
|
调用failed和messages方法来处理会优雅许多!
接下来说一下大家关心的手机验证,
1
2
3
|
Validator::extend(
'mobile'
,
function
(
$attribute
,
$value
,
$parameters
) {
return
preg_match(
"/^1[34578]{1}\d{9}$/"
,
$value
);
});
|
1
|
<span style=
"font-size: 14px; line-height: 21px; white-space: normal"
><span style=
"font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif"
>这段代码应该很熟悉吧,不过到底放在哪里合适呢?我是这么做的<br data-filtered=
"filtered"
><br data-filtered=
"filtered"
>bootstrap/app.phpj加上<br data-filtered=
"filtered"
></span></span>
|
1
|
$app
->register(App\Providers\Validate\ValidateServiceProvider::
class
);
|
然后创建对应服务类app/Providers/Validate/ValidateServiceProvider.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
namespace
App\Providers\Validate;
use
Validator;
use
Illuminate\Support\ServiceProvider;
class
ValidateServiceProvider
extends
ServiceProvider
{
public
function
boot()
{
Validator::extend(
'mobile'
,
function
(
$attribute
,
$value
,
$parameters
) {
return
preg_match(
"/^1[34578]{1}\d{9}$/"
,
$value
);
});
}
public
function
register()
{
}
}
|
加入手机验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
$input
= [
'typeid'
=> 1,
'title'
=>
'测试标题'
,
'content'
=>
'测试内容'
,
'phone'
=>
'1881'
];
$rules
= [
'typeid'
=>
'required|numeric'
,
'title'
=>
'required'
,
'content'
=>
'required'
,
'phone'
=>
'mobile'
];
$message
= [
"required"
=>
":attribute 不能为空"
,
"numeric"
=>
":attribute 格式不正确"
,
"mobile"
=>
":attribute 手机格式不正确"
];
$attributes
= [
'typeid'
=>
'分类id'
,
'title'
=>
'标题'
,
'content'
=>
'内容'
,
'phone'
=>
'联系方式'
];
|
就这样简单的实现了手机验证!
如果不想每次都传$message的话,可以看看这里\vendor\laravel\lumen-framework\resources\lang\en\validation.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
<?php
return
[
'accepted'
=>
'The :attribute must be accepted.'
,
'active_url'
=>
'The :attribute is not a valid URL.'
,
'after'
=>
'The :attribute must be a date after :date.'
,
'after_or_equal'
=>
'The :attribute must be a date after or equal to :date.'
,
'alpha'
=>
'The :attribute may only contain letters.'
,
'alpha_dash'
=>
'The :attribute may only contain letters, numbers, and dashes.'
,
'alpha_num'
=>
'The :attribute may only contain letters and numbers.'
,
'array'
=>
'The :attribute must be an array.'
,
'before'
=>
'The :attribute must be a date before :date.'
,
'before_or_equal'
=>
'The :attribute must be a date before or equal to :date.'
,
'between'
=> [
'numeric'
=>
'The :attribute must be between :min and :max.'
,
'file'
=>
'The :attribute must be between :min and :max kilobytes.'
,
'string'
=>
'The :attribute must be between :min and :max characters.'
,
'array'
=>
'The :attribute must have between :min and :max items.'
,
],
'boolean'
=>
'The :attribute field must be true or false.'
,
'confirmed'
=>
'The :attribute confirmation does not match.'
,
'date'
=>
'The :attribute is not a valid date.'
,
'date_format'
=>
'The :attribute does not match the format :format.'
,
'different'
=>
'The :attribute and :other must be different.'
,
'digits'
=>
'The :attribute must be :digits digits.'
,
'digits_between'
=>
'The :attribute must be between :min and :max digits.'
,
'dimensions'
=>
'The :attribute has invalid image dimensions.'
,
'distinct'
=>
'The :attribute field has a duplicate value.'
,
'email'
=>
'The :attribute must be a valid email address.'
,
'exists'
=>
'The selected :attribute is invalid.'
,
'file'
=>
'The :attribute must be a file.'
,
'filled'
=>
'The :attribute field is required.'
,
'image'
=>
'The :attribute must be an image.'
,
'in'
=>
'The selected :attribute is invalid.'
,
'in_array'
=>
'The :attribute field does not exist in :other.'
,
'integer'
=>
'The :attribute must be an integer.'
,
'ip'
=>
'The :attribute must be a valid IP address.'
,
'json'
=>
'The :attribute must be a valid JSON string.'
,
'max'
=> [
'numeric'
=>
'The :attribute may not be greater than :max.'
,
'file'
=>
'The :attribute may not be greater than :max kilobytes.'
,
'string'
=>
'The :attribute may not be greater than :max characters.'
,
'array'
=>
'The :attribute may not have more than :max items.'
,
],
'mimes'
=>
'The :attribute must be a file of type: :values.'
,
'mimetypes'
=>
'The :attribute must be a file of type: :values.'
,
'min'
=> [
'numeric'
=>
'The :attribute must be at least :min.'
,
'file'
=>
'The :attribute must be at least :min kilobytes.'
,
'string'
=>
'The :attribute must be at least :min characters.'
,
'array'
=>
'The :attribute must have at least :min items.'
,
],
'not_in'
=>
'The selected :attribute is invalid.'
,
'numeric'
=>
'The :attribute must be a number.'
,
'present'
=>
'The :attribute field must be present.'
,
'regex'
=>
'The :attribute format is invalid.'
,
'required'
=>
'The :attribute field is required.'
,
'required_if'
=>
'The :attribute field is required when :other is :value.'
,
'required_unless'
=>
'The :attribute field is required unless :other is in :values.'
,
'required_with'
=>
'The :attribute field is required when :values is present.'
,
'required_with_all'
=>
'The :attribute field is required when :values is present.'
,
'required_without'
=>
'The :attribute field is required when :values is not present.'
,
'required_without_all'
=>
'The :attribute field is required when none of :values are present.'
,
'same'
=>
'The :attribute and :other must match.'
,
'size'
=> [
'numeric'
=>
'The :attribute must be :size.'
,
'file'
=>
'The :attribute must be :size kilobytes.'
,
'string'
=>
'The :attribute must be :size characters.'
,
'array'
=>
'The :attribute must contain :size items.'
,
],
'string'
=>
'The :attribute must be a string.'
,
'timezone'
=>
'The :attribute must be a valid zone.'
,
'unique'
=>
'The :attribute has already been taken.'
,
'uploaded'
=>
'The :attribute failed to upload.'
,
'url'
=>
'The :attribute format is invalid.'
,
'custom'
=> [
'attribute-name'
=> [
'rule-name'
=>
'custom-message'
,
],
],
'attributes'
=> [],
];
|
默认都是英文,直接改成下面的中文配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
<?php
return
[
'accepted'
=>
':attribute必须接受'
,
'active_url'
=>
':attribute必须是一个合法的 URL'
,
'after'
=>
':attribute 必须是 :date 之后的一个日期'
,
'after_or_equal'
=>
':attribute 必须是 :date 之后或相同的一个日期'
,
'alpha'
=>
':attribute只能包含字母'
,
'alpha_dash'
=>
':attribute只能包含字母、数字、中划线或下划线'
,
'alpha_num'
=>
':attribute只能包含字母和数字'
,
'array'
=>
':attribute必须是一个数组'
,
'before'
=>
':attribute 必须是 :date 之前的一个日期'
,
'before_or_equal'
=>
':attribute 必须是 :date 之前或相同的一个日期'
,
'between'
=> [
'numeric'
=>
':attribute 必须在 :min 到 :max 之间'
,
'file'
=>
':attribute 必须在 :min 到 :max KB 之间'
,
'string'
=>
':attribute 必须在 :min 到 :max 个字符之间'
,
'array'
=>
':attribute 必须在 :min 到 :max 项之间'
,
],
'boolean'
=>
':attribute 字符必须是 true 或 false'
,
'confirmed'
=>
':attribute 二次确认不匹配'
,
'date'
=>
':attribute 必须是一个合法的日期'
,
'date_format'
=>
':attribute 与给定的格式 :format 不符合'
,
'different'
=>
':attribute 必须不同于 :other'
,
'digits'
=>
':attribute必须是 :digits 位.'
,
'digits_between'
=>
':attribute 必须在 :min 和 :max 位之间'
,
'dimensions'
=>
':attribute具有无效的图片尺寸'
,
'distinct'
=>
':attribute字段具有重复值'
,
'email'
=>
':attribute必须是一个合法的电子邮件地址'
,
'exists'
=>
'选定的 :attribute 是无效的.'
,
'file'
=>
':attribute必须是一个文件'
,
'filled'
=>
':attribute的字段是必填的'
,
'image'
=>
':attribute必须是 jpeg, png, bmp 或者 gif 格式的图片'
,
'in'
=>
'选定的 :attribute 是无效的'
,
'in_array'
=>
':attribute 字段不存在于 :other'
,
'integer'
=>
':attribute 必须是个整数'
,
'ip'
=>
':attribute必须是一个合法的 IP 地址。'
,
'json'
=>
':attribute必须是一个合法的 JSON 字符串'
,
'max'
=> [
'numeric'
=>
':attribute 的最大长度为 :max 位'
,
'file'
=>
':attribute 的最大为 :max'
,
'string'
=>
':attribute 的最大长度为 :max 字符'
,
'array'
=>
':attribute 的最大个数为 :max 个.'
,
],
'mimes'
=>
':attribute 的文件类型必须是 :values'
,
'min'
=> [
'numeric'
=>
':attribute 的最小长度为 :min 位'
,
'file'
=>
':attribute 大小至少为 :min KB'
,
'string'
=>
':attribute 的最小长度为 :min 字符'
,
'array'
=>
':attribute 至少有 :min 项'
,
],
'not_in'
=>
'选定的 :attribute 是无效的'
,
'numeric'
=>
':attribute 必须是数字'
,
'present'
=>
':attribute 字段必须存在'
,
'regex'
=>
':attribute 格式是无效的'
,
'required'
=>
':attribute 字段是必须的'
,
'required_if'
=>
':attribute 字段是必须的当 :other 是 :value'
,
'required_unless'
=>
':attribute 字段是必须的,除非 :other 是在 :values 中'
,
'required_with'
=>
':attribute 字段是必须的当 :values 是存在的'
,
'required_with_all'
=>
':attribute 字段是必须的当 :values 是存在的'
,
'required_without'
=>
':attribute 字段是必须的当 :values 是不存在的'
,
'required_without_all'
=>
':attribute 字段是必须的当 没有一个 :values 是存在的'
,
'same'
=>
':attribute和:other必须匹配'
,
'size'
=> [
'numeric'
=>
':attribute 必须是 :size 位'
,
'file'
=>
':attribute 必须是 :size KB'
,
'string'
=>
':attribute 必须是 :size 个字符'
,
'array'
=>
':attribute 必须包括 :size 项'
,
],
'string'
=>
':attribute 必须是一个字符串'
,
'timezone'
=>
':attribute 必须是个有效的时区.'
,
'unique'
=>
':attribute 已存在'
,
'url'
=>
':attribute 无效的格式'
,
'mobile'
=>
':attribute 手机号码无效'
,
'custom'
=> [
'attribute-name'
=> [
'rule-name'
=>
'custom-message'
,
],
],
'attributes'
=> [],
];
|
然后在没有传$message时,就会默认读这里了!
接下来讲讲Lumen验证的周期,当你调用下面的语句时,
1
|
Validator::make(
$input
,
$rules
,
$message
,
$attributes
);
|
会直接调用到对应的Factory.php,这可以说是一种规范,这里是vendor\illuminate\validation\Factory.php,看看对应的make函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public
function
make(
array
$data
,
array
$rules
,
array
$messages
= [],
array
$customAttributes
= [])
{
$validator
=
$this
->resolve(
$data
,
$rules
,
$messages
,
$customAttributes
);
if
(!
is_null
(
$this
->verifier)) {
$validator
->setPresenceVerifier(
$this
->verifier);
}
if
(!
is_null
(
$this
->container)) {
$validator
->setContainer(
$this
->container);
}
$this
->addExtensions(
$validator
);
return
$validator
;
}
|
然后来到resolve函数,
1
2
3
4
5
6
7
8
9
10
11
|
protected
function
resolve(
array
$data
,
array
$rules
,
array
$messages
,
array
$customAttributes
)
{
if
(
is_null
(
$this
->resolver)) {
return
new
Validator(
$this
->translator,
$data
,
$rules
,
$messages
,
$customAttributes
);
}
return
call_user_func(
$this
->resolver,
$this
->translator,
$data
,
$rules
,
$messages
,
$customAttributes
);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
namespace
Illuminate\Validation;
..
class
Validator
implements
ValidatorContract
{
...
public
function
__construct(Translator
$translator
,
array
$data
,
array
$rules
,
array
$messages
= [],
array
$customAttributes
= [])
{
$this
->initialRules =
$rules
;
$this
->translator =
$translator
;
$this
->customMessages =
$messages
;
$this
->data =
$this
->parseData(
$data
);
$this
->customAttributes =
$customAttributes
;
$this
->setRules(
$rules
);
}
}
|
make执行到这里完。
接下来,先来看看刚才用的第一个验证函数validate(),
1
2
3
4
5
6
7
8
9
|
public
function
validate()
{
if
(
$this
->fails()) {
throw
new
ValidationException(
$this
);
}
}
|
1
2
3
4
5
6
|
public
function
fails()
{
return
!
$this
->passes();
|
显而易见,一旦验证不通过则抛出异常,不太适合一般的开发。
再看看messages()
1
2
3
4
5
6
7
8
9
10
11
|
public
function
messages()
{
if
(!
$this
->messages) {
$this
->passes();
}
return
$this
->messages;
}
|
这里函数是返回所有验证不通过的信息
再看看failed()
1
2
3
4
5
6
7
8
9
|
public
function
failed()
{
return
$this
->failedRules;
}
|
这边好像验证失败也是空,晕~
接下来看passes()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public
function
passes()
{
$this
->messages =
new
MessageBag;
foreach
(
$this
->rules
as
$attribute
=>
$rules
) {
$attribute
=
str_replace
(
'\.'
,
'->'
,
$attribute
);
foreach
(
$rules
as
$rule
) {
$this
->validateAttribute(
$attribute
,
$rule
);
if
(
$this
->shouldStopValidating(
$attribute
)) {
break
;
}
}
}
foreach
(
$this
->after
as
$after
) {
call_user_func(
$after
);
}
return
$this
->messages->isEmpty();
}
|
接下来干货来了validateAttribute($attribute, $rule)函数,处理都在这里调的
1
2
|
/**
* Validate a given attribute against a rule.(根据规则验证给定属性。)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
*
* @param string
$attribute
* @param string
$rule
* @
return
void
*/
protected
function
validateAttribute(
$attribute
,
$rule
)
{
$this
->currentRule =
$rule
;
list(
$rule
,
$parameters
) = ValidationRuleParser::parse(
$rule
);
if
(
$rule
==
''
) {
return
;
}
if
((
$keys
=
$this
->getExplicitKeys(
$attribute
)) &&
$this
->dependsOnOtherFields(
$rule
)) {
$parameters
=
$this
->replaceAsterisksInParameters(
$parameters
,
$keys
);
}
$value
=
$this
->getValue(
$attribute
);
if
(
$value
instanceof
UploadedFile && !
$value
->isValid() &&
$this
->hasRule(
$attribute
,
array_merge
(
$this
->fileRules,
$this
->implicitRules))
) {
return
$this
->addFailure(
$attribute
,
'uploaded'
, []);
}
$validatable
=
$this
->isValidatable(
$rule
,
$attribute
,
$value
);
$method
=
"validate{$rule}"
;
if
(
$validatable
&& !
$this
->
$method
(
$attribute
,
$value
,
$parameters
,
$this
)) {
$this
->addFailure(
$attribute
,
$rule
,
$parameters
);
}
}
|
主要是这两段
1
2
3
4
5
|
$method
=
"validate{$rule}"
;
if
(
$validatable
&& !
$this
->
$method
(
$attribute
,
$value
,
$parameters
,
$this
)) {
$this
->addFailure(
$attribute
,
$rule
,
$parameters
);
}
|
根据规则拼接验证函数名,再调用,函数都写在了最开始引用的Concerns\ValidatesAttributes
1
2
|
use
Concerns\FormatsMessages,
Concerns\ValidatesAttributes;
|
vendor\illuminate\validation\Concerns\ValidatesAttributes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
namespace
Illuminate\Validation\Concerns;
...
trait
ValidatesAttributes
{
...
protected
function
validateNumeric(
$attribute
,
$value
)
{
return
is_numeric
(
$value
);
}
return
false;
}
elseif
(
$value
instanceof
File) {
return
(string)
$value
->getPath() !=
''
;
}
return
true;
}
...
}
|
这个就是刚才'required|numeric'的numeric对应执行的方法,不信可以在下面加上
1
2
3
4
|
protected
function
validateMobile(
$attribute
,
$value
,
$parameters
)
{
return
preg_match(
"/^1[34578]{1}\d{9}$/"
,
$value
);
}
|
把刚才的ValidateServiceProvider.php的启动注入注释掉
1
2
3
4
5
6
7
8
9
|
public
function
boot()
{
}
|
执行还是会验证,不过一般都是在外面注入,写在里面只是测试下。 |