Lumen封装接口参数验证

3月 16, 2017

“永远不要相信用户的输入是正确的”,对我们来说,是进行安全设计和安全编码的重要原则,所以在执行业务代码前,需要对用户输入的参数进行合法性判断。

在Lumen框架中,我们可以使用Validation进行数据验证,但其实现的方法比较繁琐,这里我进行了封装。以后我们只需要在控制器层添加下面方法即可进行验证,验证规则可参考这 可用的验证规则

1
2
3
4
5
6
7
8
public static function rules()
{
return [
'name' => ['required|min:3|alpha_dash', '用户名'],
'mail' => ['required|email', '邮箱'],
'password' => ['required|min:12|alpha_dash', '密码'],
];
}

写好验证规则后,需要调用这个方法并执行这些验证规则,控制器集成于Controller,在Controller里写一个验证的方法:

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
public function validator()
{
//如果不存在该方法则停止
if (!method_exists($this, 'rules')) {
return;
}

//调用子类的rules方法
$calledClass = get_called_class();
$paramRules = $calledClass::rules();
$rule = [];
$attributeName = [];
//如果没有验证规则则停止
if (empty($paramRules)) {
return;
}
foreach ($paramRules as $title => $value) {
//构建验证规则数组
$rule[$title] = $value[0];
//别名数组
$attributeName[$title] = $value[1];
}
$validation = \Validator::make($this->_inputData, $rule)->setAttributeNames($attributeName);
//验证失败抛出异常
if ($validation->fails()) {
throw new EvaException($validation->messages()->first(), Retcode::ERR_PARAM);
}
}

然后在构造方法__construct()里加入

1
$this->validator();

即可完成调用。这时就完成了参数的验证,但抛出的异常是英文的,如果想要实现翻译成中文,添加语言文件resources/lang/zh-CN/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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php

return [

/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| such as the size rules. Feel free to tweak each of these messages.
|
*/

'accepted' => ':attribute 必须接受。',
'active_url' => ':attribute 不是一个有效的网址。',
'after' => ':attribute 必须是一个在 :date 之后的日期。',
'alpha' => ':attribute 只能由字母组成。',
'alpha_dash' => ':attribute 只能由字母、数字和斜杠组成。',
'alpha_num' => ':attribute 只能由字母和数字组成。',
'array' => ':attribute 必须是一个数组。',
'before' => ':attribute 必须是一个在 :date 之前的日期。',
'between' => [
'numeric' => ':attribute 必须介于 :min - :max 之间。',
'file' => ':attribute 必须介于 :min - :max kb 之间。',
'string' => ':attribute 必须介于 :min - :max 个字符之间。',
'array' => ':attribute 必须只有 :min - :max 个单元。',
],
'boolean' => ':attribute 必须为布尔值。',
'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 必须是图片。',
'in' => '已选的属性 :attribute 非法。',
'in_array' => ':attribute 没有在 :other 中。',
'integer' => ':attribute 必须是整数。',
'ip' => ':attribute 必须是有效的 IP 地址。',
'json' => ':attribute 必须是正确的 JSON 格式。',
'max' => [
'numeric' => ':attribute 不能大于 :max。',
'file' => ':attribute 不能大于 :max kb。',
'string' => ':attribute 不能大于 :max 个字符。',
'array' => ':attribute 最多只有 :max 个单元。',
],
'mimes' => ':attribute 必须是一个 :values 类型的文件。',
'mimetypes' => ':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' => '当 :other 为 :value 时 :attribute 不能为空。',
'required_unless' => '当 :other 不为 :value 时 :attribute 不能为空。',
'required_with' => '当 :values 存在时 :attribute 不能为空。',
'required_with_all' => '当 :values 存在时 :attribute 不能为空。',
'required_without' => '当 :values 不存在时 :attribute 不能为空。',
'required_without_all' => '当 :values 都不存在时 :attribute 不能为空。',
'same' => ':attribute 和 :other 必须相同。',
'size' => [
'numeric' => ':attribute 大小必须为 :size。',
'file' => ':attribute 大小必须为 :size kb。',
'string' => ':attribute 必须是 :size 个字符。',
'array' => ':attribute 必须为 :size 个单元。',
],
'string' => ':attribute 必须是一个字符串。',
'timezone' => ':attribute 必须是一个合法的时区值。',
'unique' => ':attribute 已经存在。',
'uploaded' => ':attribute 上传失败。',
'url' => ':attribute 格式不正确。',

/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention 'attribute.rule' to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/

'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],

/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of 'email'. This simply helps us make messages a little cleaner.
|
*/

'attributes' => [
'name' => '名称',
'username' => '用户名',
'email' => '邮箱',
'first_name' => '名',
'last_name' => '姓',
'password' => '密码',
'password_confirmation' => '确认密码',
'city' => '城市',
'country' => '国家',
'address' => '地址',
'phone' => '电话',
'mobile' => '手机',
'age' => '年龄',
'sex' => '性别',
'gender' => '性别',
'day' => '天',
'month' => '月',
'year' => '年',
'hour' => '时',
'minute' => '分',
'second' => '秒',
'title' => '标题',
'content' => '内容',
'description' => '描述',
'excerpt' => '摘要',
'date' => '日期',
'time' => '时间',
'available' => '可用的',
'size' => '大小',
],

];

这时抛出的异常就是中文的了,如下例子:

1
2
3
4
{
"code": -1,
"msg": "标题 不能为空。"
}

上述的例子的验证规则可写可不写,实际的项目中是必须要写的,实现这个效果,可以在Controller的类名前添加abstract修饰词,使其变为抽象类,实现一个抽象方法:

1
abstract public static function rules();

这样就规定了子类必须要用rules()这个方法。