-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathValidator.php
More file actions
196 lines (177 loc) · 6.79 KB
/
Validator.php
File metadata and controls
196 lines (177 loc) · 6.79 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<?php
namespace Shuc324\Validation;
use Closure;
class Validator
{
private $var;
private $val;
private $data = [];
private $parseData = [];
public function __construct($data, $format)
{
if (!is_array($data) || empty($data)) {
throw new ValidationException('待校验数据必须为非空数组', 1);
}
if (!is_array($format) || empty($format)) {
throw new ValidationException('字段校验格式必须设置并为数组', 1);
}
return $this->start($data, $format);
}
protected function ruleExplode($rules)
{
return is_array($rules) ? $rules : explode('|', $rules);
}
protected function parse(array $format)
{
return array_map(function ($item) use ($this) {
return $this->ruleExplode($item);
}, $format);
}
protected function parseData(array $format)
{
$parse = $this->parse($format);
foreach ($parse as $name => $rules) {
foreach ($rules as $rule) {
$data = explode(':', $rule);
$method = array_shift($data);
$this->parseData[$name][$method] = explode(',', array_shift($data));
}
}
}
protected function validatorMethodName($validator)
{
return 'v' . ucfirst($validator);
}
// 没办法只能用eval
protected function evalArray(array $keys, $value)
{
$arr = []; $str = '$arr';
array_map(function($key) use (&$str) {
$key = is_numeric($key) ? intval($key) : '\'' . $key . '\'';
$str .= '[' . $key . ']';
}, $keys);
eval($str . ' = ' . $value . ';');
return $arr;
}
protected function start(array $data, array $format)
{
$this->parseData($format);
foreach ($data as $field => $value) {
// 此处去支持点语法(数组,列表)验证
$pieces = explode('.', $field);
if (!isset($this->parseData[$pieces[0]])) {
continue;
}
switch (count($pieces)) {
// 异常
case 0:
throw new ValidationException('字段名不能为空', 1);
break;
// value
case 1:
foreach ($this->parseData[$field] as $method => $argument) {
if (!isset($this->data[$field])) {
$this->data[$field] = $value;
}
array_unshift($argument, $this->data[$field]);
if (method_exists($this, $this->validatorMethodName($method))) {
$this->var = $field;
$this->data[$field] = call_user_func_array([$this, $this->validatorMethodName($method)], $argument);
$this->var = null;
} else {
throw new ValidationException('mongoDB字段验证方法' . get_class($this) . '->' . $this->validatorMethodName($method) . '()不存在', 1);
}
}
break;
// array
default:
$array = $this->evalArray($pieces, $value);
foreach ($this->parseData[$pieces[0]] as $method => $argument) {
if (!isset($this->data[$field])) {
$this->data[$field] = $array[$pieces[0]];
}
array_unshift($argument, $this->data[$field]);
if (method_exists($this, $this->validatorMethodName($method))) {
$this->val = $value;
$this->var = $pieces[0];
$this->data[$field] = call_user_func_array([$this, $this->validatorMethodName($method)], $argument);
$this->val = null;
$this->var = null;
} else {
throw new ValidationException('mongoDB字段验证方法' . get_class($this) . '->' . $this->validatorMethodName($method) . '()不存在', 1);
}
}
break;
}
}
return $this->data;
}
/*************************** validatorMethodName ***************************/
# enum:0/1/2
protected function vEnum($var, $str)
{
if (!in_array($var, explode('/', $str))) {
throw new ValidationException('字段' . $this->var . '不在' . $str . '范围内');
}
return $var;
}
# number
protected function vNumber($var)
{
if (!(is_int($var) || is_float($var))) {
throw new ValidationException('字段' . $this->var . '必须为数字');
}
return $var;
}
# string
protected function vString($var)
{
if (!is_string($var)) {
throw new ValidationException('字段' . $this->var . '必须为字符串');
}
return $var;
}
# array
protected function vArray($var)
{
if (!is_array($var)) {
throw new ValidationException('字段' . $this->var . '必须为数组');
}
// 数组类型必须参照此处
return isset($this->val) ? $this->val : $var;
}
# list:int,list:string,list:array,list:object
protected function vList($var, $type = 'int')
{
if (is_array($var)) {
foreach ($var as $key => $value) {
if (!is_int($key)) {
throw new ValidationException('字段' . $this->var . '必须为列表');
}
if (!call_user_func('is_' . $type, $value)) {
throw new ValidationException('字段' . $this->var . '必须为' . $type . '列表');
}
}
} else {
throw new ValidationException('字段' . $this->var . '必须为列表');
}
// 数组类型必须参照此处
return isset($this->val) ? $this->val : $var;
}
# callBack:\namespace\class@method
protected function vCallBack($var, Closure $callable)
{
list($class, $method) = explode('@', $callable);
if (!is_array($var)) {
throw new ValidationException('回调验证只支持数组字段');
}
if (!class_exists($class, $method)) {
throw new ValidationException('回调方法' . implode('::', [$class, $method]) . '未定义');
}
if (!call_user_func_array([$class, $method], [$var])) {
throw new ValidationException('字段' . $this->var . '不能通过' . implode('::', [$class, $method]) . '的验证');
}
// 数组类型必须参照此处
return isset($this->val) ? $this->val : $var;
}
}