- 1. UML类图
- 2. 方法详解
- 2.1 构造方法
__construct() - 2.2 设置服务注入
maker()方法 - 2.3 设置语言对象
setLang()方法 - 2.4 设置Db对象
setDb()方法 - 2.6 添加字段验证规则
rule()方法 - 2.10 设置当前验证场景
scene()方法 - 2.11 判断验证场景是否已定义
hasScene()方法 - 2.12 设置验证方式是批量验证
batch()方法 - 2.14 指定需要验证的字段列表
only()方法 - 2.19 验证单个字段规则
checkItem()方法 - 2.20 获取当前验证类型及规则
getValidateType()方法 - 2.22 获取数据值
getDataValue()方法 - 2.23 验证是否和某个字段的值一致
confirm()方法 - 2.24 验证是否和某个字段的值是否不同
different()方法 - 2.25 验证是否大于等于某个值
egt()方法 - 2.26 验证是否大于某个值
gt()方法 - 2.27 验证是否小于等于某个值
elt()方法 - 2.28 验证是否小于某个值
lt()方法 - 2.29 验证是否等于某个值
eq()方法 - 2.30 必须验证
must()方法 - 2.31 验证字段是否是有效格式is()方法
- 2.32 判断图像类型
getImageType()方法 - 2.33 验证表单令牌
token()方法 - 2.34 验证是否是合格的域名或IP
activeUrl()方法 - 2.35 验证是否是有效IP
ip()方法 - 2.36 检测上传文件后缀
checkExt()方法 - 2.37 检测上传文件大小
checkSize()方法 - 2.38 检测上传文件MIME类型
checkMime()方法 - 2.39 验证上传文件后缀
fileExt()方法 - 2.40 验证上传文件MIME类型
fileMime()方法 - 2.41 验证上传文件大小
fileSize()方法 - 2.42 验证图片的宽高及类型
image()方法 - 2.43 验证日期和时间是否符合指定格式dateFormat()方法
- 2.44 验证是否唯一
unique()方法 - 2.45 使用filter_var方式验证
filter()方法 - 2.46 验证某个字段等于某个值的时候必须
requireIf()方法 - 2.47 通过回调方法验证某个字段是否必须
requireCallback()方法 - 2.48 验证某个字段有值的情况下必须
requireWith()方法 - 2.59 验证某个字段在没有值得情况下必须
requireWithout()方法 - 2.60 验证是否在范围内
in()方法 - 2.61 验证是否不再某个范围内
notin()方法 - 2.62 验证数据
between()方法 - 2.63 验证数据
notbetween()方法 - 2.64 验证数据长度
length()方法 - 2.65 验证数据最大长度
maxLength()方法 - 2.66 验证数据最小长度
min()方法 - 2.67 验证日期
after()方法 - 2.68 验证日期
before()方法 - 2.69 验证日期
afterWith()方法 - 2.70 验证容器
beforeWith()方法 - 2.71 验证有效期
expire()方法 - 2.72 验证IP许可
allowIp()方法 - 2.73 验证IP禁用
denyIp()方法 - 2.74 使用正则验证数据
regex()方法 - 2.75 获取错误信息
getError()方法 - 2.76 获取验证规则的错误提示信息
getRuleMsg()方法 - 2.77 获取验证规则的错误提示信息
parseErrorMsg()方法 - 2.78 错误信息数组处理
errorMsgIsArray()方法 - 2.79 动态方法
__call()
- 2.1 构造方法
- 3. 助手函数
1. UML类图
2. 方法详解
2.1 构造方法 __construct()
- 参数:无
- 返回:无
源码:如下
public function __construct(){//这里类的静态属性$maker是注入服务的数组,遍历执行这些回调函数,参数是当前validate对象if (!empty(static::$maker)) {foreach (static::$maker as $maker) {call_user_func($maker, $this);}}}
说明:
- 对象在构造时会遍历
$maker(注入服务的闭包数组)的静态属性,通过call_user_func()执行,传递当前对象作为服务的参数。2.2 设置服务注入
maker()方法
- 参数:
[Closure](https://www.php.net/manual/zh/class.closure.php)``$maker 注入的服务
- 返回:无
- 源码:如下
public static function maker(Closure $maker){static::$maker[] = $maker;}
2.3 设置语言对象 setLang() 方法
- 参数:
Lang $lang 语言对象
Db $db Db对象
- 返回:无
- 源码:如下
```php
public function setDb(Db $db)
{
}$this->db = $db;
<a name="8IKf5"></a>#### 2.5 设置Request对象 `setRequest()` 方法- **参数:**`Request $request` 请求对象- **返回:**无- **源码:**如下```phppublic function setRequest(Request $request){$this->request = $request;}
2.6 添加字段验证规则 rule() 方法
- 参数:
string|array $name 字段名称|规则数组Closure|ValidateRule|string|array $rule 验证规则|字段描述信息
- 返回:
self 源码:如下
public function rule($name, $rule = ''){if (is_array($name)) {$this->rule = $name + $this->rule;if (is_array($rule)) {$this->field = array_merge($this->field, $rule);}} else {$this->rule[$name] = $rule;}return $this;}
说明:
- 参数
$name为数组的情况,表示操作为批量添加,操作会将对象的$rule属性和$name参数进行合并,$name将具有合并优先级,$name为字符串时是单一添加,操作会设置对象$rule属性数组的对应$name的索引的值为$rule; - 数组合并运算符
+运算符把右边的数组元素附加到左边的数组后面,两个数组中都有的键名,则只用左边数组中的,右边的被忽略,与array_merge()的区别是+运算符前面的数组有合并优先级,而array_merge()后面的数组有合并优先级; - 参数
$name$rule都为数组的情况,会将对象的$field(验证字段描述)属性和$rule参数进行合并,$rule参数将具有合并优先级;
- 用法示例: ```php $validator = new Validate();
//第一种用法,批量设置字段age的验证规则为必须切不能超过25 $validator->rule([‘age’ => ‘require|max:25’]);
//第二种用法,同上设置单一字段的验证规则 $validator->rule(‘age’, ‘require|max:25’);
//第三种用法,批量设置字段age的验证规则为必须且不能超过25,并设置验证字段描述为’年龄’ $validator->rule([‘age’ => ‘require|max:25’], [‘age’ => ‘年龄’]);
//验证规则为闭包函数,闭包函数的value参数是验证字段的值,data参数是验证数组 $validator->rule(‘age’, function($value, $data){ return $value === 1 });
//验证规则为ValidateRule对象 $validator->rule(‘age’, new ValidateRule());
<a name="uErR5"></a>#### 2.7 注册验证(类型)规则 `extend()` 方法- **参数:**`string $type` 验证规则类型<br />`callable $callback` callback方法(或闭包)<br />`string $message` 验证失败提示信息- **返回:**`self`- **源码:**如下```phppublic function extend(string $type, callable $callback = null, string $message = null){$this->type[$type] = $callback;if ($message) {$this->typeMsg[$type] = $message;}return $this;}
- 说明:
- 对象的
$type自定义验证类型属性会添加以参数$type作为索引以参数$callback作为值得数组项,如果有参数$message那么会在$typeMsg(默认规则提示)属性添加以参数$type索引值为$message的数组项; $callback代表的函数可接受$value(字段的值),$rule(通常为验证规则:后的值),$data(需验证的数组),$field(验证的字段),$title(验证字段描述)。
- 用法示例: ```php $validator = new Validate();
//设置自定义验证规则captcha和对应的默认规则提示 function captcha_validate_callback($value, $rule, $data, $field, $title) { … } $validator->extend(‘captcha’, ‘capthca_validate_callback’, ‘:attribute not valid’);
//设置自定义验证规格为类的静态函数 $validator->extend(‘captcha’, ‘SomeClass::someMethod’);
//设置自定义验证规则为对象的方法 $validator->extend(‘captcha’, [$object, ‘someMethod’]);
//设置自定义验证规则为匿名函数 $validator->extend(‘captcha’, function(){ … });
<a name="vohyN"></a>#### 2.8 设置验证(类型)规则的默认提示信息 `setTypeMsg()` 方法- **参数:**`string|array $type` 验证规则类型<br />`string $msg` 验证失败提示信息- **返回:**`self`- **源码:**如下```phppublic function setTypeMsg($type, string $msg = null): void{if (is_array($type)) {$this->typeMsg = array_merge($this->typeMsg, $type);} else {$this->typeMsg[$type] = $msg;}}
- 说明:
$type参数为数组进行批量设置,$type参数为字符串为单一设置;
- 用法示例: ```php $validator = new Validate();
//批量设置 $validator->setTypeMsg([‘captcha’ => ‘:attribute not a valid captcha’]);
//单一设置 $validator->setTypeMsg(‘captcha’, ‘:attribute not a valid captcha’);
<a name="P9DwQ"></a>#### 2.9 设置提示信息 `message()` 方法- **参数:**`array $msg` 错误信息- **返回:**`self`- **源码:**如下```phppublic function message(array $message){$this->message = array_merge($this->message, $message);return $this;}
- 说明:
$message属性和$typeMsg属性之间的区别:没有$message才会显示$typeMsg定义的提示信息;$typeMsg会经过编译取代变量;- 错误信息可以通过属性定义和方法定义。
用法示例:
$validator = new Validate();$validator->message(['name.require' => '姓名必须']);
2.10 设置当前验证场景 scene() 方法
- 参数:
string $name 错误信息
- 返回:
self 源码:如下
public function scene(string $name){$this->currentScene = $name;return $this;}
说明:
- 参数:
string $name 错误信息
- 返回:
bool 源码:如下
public function hasScene(string $name): bool{return isset($this->scene[$name]) || method_exists($this, 'scene' . $name);}
说明:
场景定义的方法: 可以通过类的属性
$scene也可以通过定义方法sceneXXX()定义, 如下:class User extends Validate{protected $rule = ['name' => 'require|max:25','age' => 'number|between:1,120','email' => 'email',];protected $message = ['name.require' => '名称必须','name.max' => '名称最多不能超过25个字符','age.number' => '年龄必须是数字','age.between' => '年龄只能在1-120之间','email' => '邮箱格式错误',];//第一种方法,定义类的属性protected $scene = ['edit' => ['name','age'],];//第二种方法,定义类的方法public function sceneEdit(){return $this->only(['name','age'])->append('name', 'min:5')->remove('age', 'between')->append('age', 'require|max:100');}}
2.12 设置验证方式是批量验证
batch()方法
- 参数:无
- 返回:
self - 源码:如下
```php
public function batch(bool $batch = true)
{
$this->batch = $batch;
return $this; }
- **说明:**1. 默认情况下,一旦有某个数据的验证规则不符合,就会停止后续数据及规则的验证,批量验证会完成后续数据及规则的验证;<a name="O34xM"></a>#### 2.13 设置验证失败后是否抛出异常 `failException()` 方法- **参数:**`bool $fail` 是否抛出异常- **返回:**`self`- **源码:**如下```phppublic function failException(bool $fail = true){$this->failException = $fail;return $this;}
- 说明:
- 默认情况
check()结果是通过函数返回值的方式返回的,设置了$failException属性,验证失败直接抛出ValidateException异常;2.14 指定需要验证的字段列表
only()方法
- 参数:
array $fields 字段名
- 返回:
self - 源码:如下
```php
public function only(array $fields)
{
$this->only = $fields;
return $this; }
- **说明:**1. 对象设置了`$only`属性,进行验证时只验证`$only`属性指定的字段;<a name="2HTEv"></a>#### 2.15 移除某个字段的验证规则 `remove()` 方法- **参数:**`string|array $field` 字段名<br />`Closure|ValidateRule|array|string|true $rule` 验证规则- **返回:**`self`- **源码:**如下```phppublic function remove($field, $rule = null){if (is_array($field)) {foreach ($field as $key => $rule) {if (is_int($key)) {$this->remove($rule);} else {$this->remove($key, $rule);}}} else {if (is_string($rule)) {$rule = explode('|', $rule);}$this->remove[$field] = $rule;}return $this;}
- 说明:
- 这个方法不是将对象的
$rule属性中对应的规则删除,只是在$remove属性中标记不需要验证的规则; $field参数是数组时使用了递归的方法;$validator->remove('field', 'rule1')->remove('field', 'rule2')这种方式不成功,应该用$validator->remove('field', 'rule1|rule2')或者$validator->remove('field', ['rule1', 'rule2'])的方式;- $rule参数为true时移除所有规则;
- 用法示例: ```php $validator = new Validate();
//第一种,$field是字符串,$rule是数组,$remove=[‘field’ => [‘rule1’, ‘rule2’]] $validator->remove(‘field’, [‘rule1’,’rule2’]);
//第二种,$field是字符串,$rule是用|符号分割的字符串, $remove=[‘field’ => [‘rule1’, ‘rule2’]] $validator->remove(‘field’, ‘rule1|rule2’);
//第三种,$field是普通数组, $remove = [‘field1’ => null, ‘fidle2’ => null] $validator->remove([‘field1’, ‘field2’]);
//第四种,$field是关联数组, $remove = [‘field1’ => [‘rule1’, ‘rule2’], ‘field2’ => [‘rule3’, ‘rule4’]] $validator->remove([‘field1’ => ‘rule1|rule2’, ‘field2’ => [‘rule3’, ‘rule4’]]);
//第五种,$rule参数为true,移除所有规则, $remove = [‘field’ => true] $validator->remove(‘field’, true);
<a name="LWBxQ"></a>#### 2.16 追加某个字段的验证规则 `append()` 方法- **参数:**`string|array $field` 字段名<br />`Closure|ValidateRule|array|string $rule` 验证规则- **返回:**`self`- **源码:**如下```phppublic function append($field, $rule = null){if (is_array($field)) {foreach ($field as $key => $rule) {$this->append($key, $rule);}} else {if (is_string($rule)) {$rule = explode('|', $rule);}$this->append[$field] = $rule;}return $this;}
- 说明:
- 这个方法不是将对象的
$rule属性中添加对应的规则,只是在$append属性中标记追加的验证的规则; $field参数是数组时使用了递归的方法;
- 用法示例: ```php $validator = new Validate(); //第一种,$field是字符串,$rule是数组, $append = [‘field’ => [‘rule1’, ‘rule2’]] $validator->append(‘field’, [‘rule1’,’rule2’]);
//第二种,$field是字符串,$rule是用|符号分割的字符串,$append = [‘field’ => [‘rule1’, ‘rule2’]] $validator->append(‘field’, ‘rule1|rule2’);
//第三种,$field是关联数组, $append = [‘field1’ => [‘rule1’, ‘rule2’]]; $validator->append([‘field1’ => ‘rule1|rule2’]);
<a name="9xgxH"></a>#### 2.17 自动验证 `check()` 方法- **参数:**`array $data` 待验证数据<br />`array $rules` 验证规则数组- **返回:**`bool`- **源码:**如下```phppublic function check(array $data, array $rules = []): bool{//清空验证失败错误信息数组$this->error = [];//$rules参数为空的时候,验证规则采用对象$rule属性,否则验证规则采用参数if (empty($rules)) {//读取验证规则$rules = $this->rule;}//根据验证当前验证场景设置当前对象的$only $append $remove属性if ($this->currentScene) {$this->getScene($this->currentScene);}//将$append中的验证规则添加到$rule属性中,$append的验证规则优先级是低于$rule的//$rule属性字段的验证规则,$append会被忽略foreach ($this->append as $key => $rule) {if (!isset($rules[$key])) {$rules[$key] = $rule;}}//遍历验证规则属性$ruleforeach ($rules as $key => $rule) {//'field' => 'rule1|rule2...'//'field' => ['rule1','rule2',...]//'age|年龄' => 'number|between:1,120'if (strpos($key, '|')) {//字段|描述 用于指定属性名称list($key, $title) = explode('|', $key);} else {$title = $this->field[$key] ?? $key;}//场景检测,只有设置了only并且当前字段不在only数组中,跳出遍历if (!empty($this->only) && !in_array($key, $this->only)) {continue;}//获取数据 支持二维数组$value = $this->getDataValue($data, $key);//字段验证//rule是闭包函数,执行闭包函数带参数value和dataif ($rule instanceof Closure) {$result = call_user_func_array($rule, [$value, $data]);//rule是ValidateRule对象} elseif ($rule instanceof ValidateRule) {//验证因子$result = $this->checkItem($key, $value, $rule->getRule(), $data, $rule->getTitle() ?: $title, $rule->getMsg());//rule是数组或者字符串} else {$result = $this->checkItem($key, $value, $rule, $data, $title);}//验证失败if (true !== $result) {//没有返回true 则表示验证失败if (!empty($this->batch)) {//批量验证$this->error[$key] = $result;//不是批量验证直接抛出异常或者停止后续验证返回false} elseif ($this->failException) {throw new ValidateException($result);} else {$this->error = $result;return false;}}}//循环结束if (!empty($this->error)) {if ($this->failException) {throw new ValidateException($this->error);}return false;}return true;}
- 说明:
- 如果通过
scene()方法设置了$currentScene属性,同时在对象中设置的$append $only $remove属性将会清空,按$scene属性或sceneXXX()方法的定义设置$append $only $remove属性,结论就是scene() append() only() remove()方法不要在对象上同时使用,append() only() remove()方法在场景定义方法sceneXXX()中使用; check($data, array $rules)接收第二个参数$rule,有第二个参数的时候,类中定义的$rules属性将不起作用;- 支持多维数组;
$rule属性为$key => $value数组,$value可以是字符串 如'require|max:20', 可以是数组 如['require', 'max' => 20],可以是闭包函数,如function($value){return $value===1 ? true : false},还可以是ValidateRule对象,如ValidateRule::isRequire()->max(20);闭包函数通过call_user_func_array($rule, [$value, $data])执行,ValidateRule对象通过checkItem($key, $value, $validateRule->getRule(), $data, $title)执行。
- 用法示例:
```php
$validator = new Validate();
//说明1 示例
$validator->scene(‘edit’)
//only remove append将不起作用->only(['name', 'age'])->remove('sex', 'rule1|rule2')->append('score', 'rule3|rule4')->check($data);
//说明2 示例 验证规则仅仅是check的参数$rules $validator->check($data, [‘name’ => ‘rule1|rule2’]);
//说明3 示例 多维数组的验证 $validator->check( [ ‘rule1’ => [‘rule2’ => 13], ], [ ‘rule1.rule2’ => ‘require|max:20’ ] )
<a name="rk3Hx"></a>#### 2.18 根据验证规则验证数据 `checkRule()` 方法- **参数:**`mixed $value` 待验证数据<br />`Closure|ValidateRule|array|string $rules` 验证规则数组- **返回:**`bool`- **源码:**如下```phppublic function checkRule($value, $rules): bool{//$rules是闭包函数直接执行if ($rules instanceof Closure) {return call_user_func_array($rules, [$value]);//$rules是ValiateRule对象,调用对象方法getRule()返回规则数组} elseif ($rules instanceof ValidateRule) {$rules = $rules->getRule();//$rules是字符串,转换为数组} elseif (is_string($rules)) {$rules = explode('|', $rules);}//遍历$rules数组foreach ($rules as $key => $rule) {//单个$rule是闭包if ($rule instanceof Closure) {$result = call_user_func_array($rule, [$value]);} else {//判断验证类型list($type, $rule) = $this->getValidateType($key, $rule);//有自定义的验证(类型)规则用自定的验证(类型)规则,否则用Validate的内置规则$callback = $this->type[$type] ?? [$this, $type];$result = call_user_func_array($callback, [$value, $rule]);}//验证失败if (true !== $result) {if ($this->failException) {throw new ValidateException($result);}return $result;}}return true;}
- 说明:
check()方法与checkRule()方法的比较不同之处:一,check()可以省略$rules参数,用对象的属性$rule进行验证,而checkRule()不可以省略$rules参数,二、check()可以进行批量验证,checkRule()不可以;checkRule()更适合自由度高的验证;
用法示例:
$validator = new Validate();$validator->checkRule(['age' => 13], '['age' => 'between:1-100']');//或者$validator->checkRule(12, 'require|between:1-100');
2.19 验证单个字段规则
checkItem()方法参数:
string $field 字段名mixed $value 字段值array|string $rules 验证规则array $data 验证数据string $title 字段描述array $msg 提示信息
- 返回:
bool 源码:如下
protected function checkItem(string $field, $value, $rules, $data, string $title = '', array $msg = []){if (isset($this->remove[$field]) && true === $this->remove[$field] && empty($this->append[$field])) {//字段已经移除 无需验证return true;}//支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]if (is_string($rules)) {$rules = explode('|', $rules);}if (isset($this->append[$field])) {//追加额外的验证规则$rules = array_unique(array_merge($rules, $this->append[$field]), SORT_REGULAR);}$i = 0;foreach ($rules as $key => $rule) {if ($rule instanceof Closure) {$result = call_user_func_array($rule, [$value, $data]);$info = is_numeric($key) ? '' : $key;} else {//判断验证类型list($type, $rule, $info) = $this->getValidateType($key, $rule);if (isset($this->append[$field]) && in_array($info, $this->append[$field])) {} elseif (isset($this->remove[$field]) && in_array($info, $this->remove[$field])) {// 规则已经移除$i++;continue;}if (isset($this->type[$type])) {$result = call_user_func_array($this->type[$type], [$value, $rule, $data, $field, $title]);} elseif ('must' == $info || 0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {$result = call_user_func_array([$this, $type], [$value, $rule, $data, $field, $title]);} else {$result = true;}}if (false === $result) {//验证失败 返回错误信息if (!empty($msg[$i])) {$message = $msg[$i];if (is_string($message) && strpos($message, '{%') === 0) {$message = $this->lang->get(substr($message, 2, -1));}} else {$message = $this->getRuleMsg($field, $title, $info, $rule);}return $message;} elseif (true !== $result) {// 返回自定义错误信息if (is_string($result) && false !== strpos($result, ':')) {$result = str_replace(':attribute', $title, $result);if (strpos($result, ':rule') && is_scalar($rule)) {$result = str_replace(':rule', (string) $rule, $result);}}return $result;}$i++;}return $result;}
2.20 获取当前验证类型及规则
getValidateType()方法参数:
mixed $key $rules数组键mixed $rule $rules数组值
- 返回:
array 源码:如下 ```php protected function getValidateType($key, $rule): array {
//判断验证类型,如[‘>=’ => 10],将返回[‘egt’, ‘10’, ‘egt’] if (!is_numeric($key)) {if (isset($this->alias[$key])) {// 判断别名$key = $this->alias[$key];}return [$key, $rule, $key];
}
//如[0 => '>=:10'],将返回['egt', '10', 'egt']
if (strpos($rule, ‘:’)) {
list($type, $rule) = explode(':', $rule, 2);if (isset($this->alias[$type])) {// 判断别名$type = $this->alias[$type];}$info = $type;//如[0 => 'ip'], 将返回['ip', '', 'ip']
} elseif (method_exists($this, $rule)) {
$type = $rule;$info = $rule;$rule = '';//如[0 => 'accepted'], 将返回['is', 'accepted', 'is']
} else {
$type = 'is';$info = $rule;
}
return [$type, $rule, $info]; }
- **说明:**1. `getValidateType(0, 'require')` 返回 `['is', 'require', 'is']`;1. `getValidateType('max', 25)` 返回`['max', 25, 'max']`;1. `getValidateType('same' 25)` 返回`['eq', 25, 'eq']`;1. `getValidateType(0, 'max:25')` 返回`['max', 25, 'max']`;1. `getValidateType(1, '=:25')` 返回`['eq', 25, 'eq']`;1. `getValidateType(1, 'confirm:pwd')` 返回`['confirm', 'pwd', 'confirm']`<a name="MNN2V"></a>#### 2.21 获取数据验证的场景 `getScene()` 方法- **参数:**`string $scene` 验证场景- **返回:**无- **源码:**如下```phpprotected function getScene(string $scene): void{$this->only = $this->append = $this->remove = [];if (method_exists($this, 'scene' . $scene)) {call_user_func([$this, 'scene' . $scene]);} elseif (isset($this->scene[$scene])) {// 如果设置了验证适用场景$this->only = $this->scene[$scene];}}
- 说明:
getScene()方法会清空对象的$only $remove $append属性;- 方法会根据
sceneXXX()方法重新定义$only $remove $append属性; - 方法会根据对象
$scene属性定义$only属性; - 场景方法定义
sceneXXX()优先级高于属性定义$scene。2.22 获取数据值
getDataValue()方法
- 参数:
array $data 数据string $key 数据标识
- 返回:
mixed 源码:如下
protected function getDataValue(array $data, $key){//如: getDataValue($data, '23') 将返回23if (is_numeric($key)) {$value = $key;//如: getDataValue(['key1' => ['key2' => 23]], 'key1.key2')将返回23} elseif (is_string($key) && strpos($key, '.')) {// 支持多维数组验证foreach (explode('.', $key) as $key) {if (!isset($data[$key])) {$value = null;break;}$value = $data = $data[$key];}} else {$value = $data[$key] ?? null;}return $value;}
说明:
getDataValue(['apple'], 1)返回的是1,这有什么用处?这是像egt:25这样的规则,type会是egt,rule会是25,info会是egt,在egt函数中会调用getDataValue($data, 25),这个时候值在规则中已经定好,不需要从指定字段取值;getDataValue(['key1' => ['key2' => 'value']], 'key1.key2')返回value;- 不存在返回
null;2.23 验证是否和某个字段的值一致
confirm()方法
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据string $field 字段名
- 返回:
bool 源码:如下
public function confirm($value, $rule, array $data = [], string $field = ''): bool{if ('' == $rule) {if (strpos($field, '_confirm')) {$rule = strstr($field, '_confirm', true);} else {$rule = $field . '_confirm';}}return $this->getDataValue($data, $rule) === $value;}
说明:
$rule = ['pwd|密码' => 'require|confirm:repwd']这样的验证规则要check()时会调用checkItem('pwd', 密码值, $rule, $data, '密码'),checkItem再将$rule分解为数组['require', 'confirm:repwd']遍历规则,遍历到confirm:repwd会分解成[type, rule, info]就是['confirm', 'repwd', 'confirm']调用此函数confirm(密码值, 'repwd', $data, 'pwd');rule为空代表的时rule规则不带:冒号后的内容,自动匹配验证规则,要验证的字段为a, 会去和confirm_a字段进行比较;要验证的字段为confirm_a,会去和a字段进行比较;strstr($haystack, $needle, $before_needel)返回haystack字符串从needle第一次出现的位置开始到haystack结尾的字符串,before_needle若为true,strstr()将返回needle在haystack中的位置之前的部分;- 规则可写为
confirm:fieldconfirm2.24 验证是否和某个字段的值是否不同
different()方法
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function different($value, $rule, array $data = []): bool{return $this->getDataValue($data, $rule) != $value;}
说明:
$rule=['field' => 'different:field2']会调用different(field的值, 'field2', $data);- 规则可写为
different:fielddifferent:30。2.25 验证是否大于等于某个值
egt()方法
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function egt($value, $rule, array $data = []): bool{return $value >= $this->getDataValue($data, $rule);}
说明:
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function gt($value, $rule, array $data = []): bool{return $value > $this->getDataValue($data, $rule);}
说明:
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function elt($value, $rule, array $data = []): bool{return $value <= $this->getDataValue($data, $rule);}
说明:
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function lt($value, $rule, array $data = []): bool{return $value < $this->getDataValue($data, $rule);}
说明:
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function eq($value, $rule): bool{return $value == $rule;}
说明:
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function must($value, $rule = null): bool{return !empty($value) || '0' == $value;}
说明:
- 参数:
mixed $value 字段的值string $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function is($value, string $rule, array $data = []): bool{switch (Str::camel($rule)) {case 'require':// 必须$result = !empty($value) || '0' == $value;break;case 'accepted':// 接受$result = in_array($value, ['1', 'on', 'yes']);break;case 'date':// 是否是一个有效日期$result = false !== strtotime($value);break;case 'activeUrl':// 是否为有效的网址$result = checkdnsrr($value);break;case 'boolean':case 'bool':// 是否为布尔值$result = in_array($value, [true, false, 0, 1, '0', '1'], true);break;case 'number':$result = ctype_digit((string) $value);break;case 'alphaNum':$result = ctype_alnum($value);break;case 'array':// 是否为数组$result = is_array($value);break;case 'file':$result = $value instanceof File;break;case 'image':$result = $value instanceof File && in_array($this->getImageType($value->getRealPath()), [1, 2, 3, 6]);break;case 'token':$result = $this->token($value, '__token__', $data);break;default:if (isset($this->type[$rule])) {// 注册的验证规则$result = call_user_func_array($this->type[$rule], [$value]);} elseif (function_exists('ctype_' . $rule)) {// ctype验证规则$ctypeFun = 'ctype_' . $rule;$result = $ctypeFun($value);} elseif (isset($this->filter[$rule])) {// Filter_var验证规则$result = $this->filter($value, $this->filter[$rule]);} else {// 正则验证$result = $this->regex($value, $rule);}}return $result;}
说明
require:value不能是"",null,undefined,array();accepted:value只能是'1', 'on', 'yes';date:value是能strtotime()函数接收的日期时间格式;activeUrl:value会用checkdnsrr()函数进行域名或ip的dns检测;bool和boolean:value的值和类型要匹配true,false, 0, 1, '0', '1';number:value的值会转换为字符串用用ctype_digit()进行检测,注意"12.31",检测会是false,因为.的原因;alphaNum:value的值会用ctype_alnum()进行检测,[A-Za-z0-9];array:value的会用is_array()进行检测;file: 判断value的值是否是think\File类的实例;image:[1,2,3,6]代表的是[gif, jpeg, png, bmp],value的值是think\File类的实例;token:表单令牌的验证,会交给Request的checkToken方法完成;- 可以通过
$type属性注册自定义的类型; alpha对应ctype_alpha;cntrl对应ctype_antrl;digit对应ctype_digit;graph对应ctype_graph,是可打印(显示)字符检测,不包括空格;lower对应ctype_lower,小写字符检测;print对应ctype_print,是可打印(显示)字符检测,包括空格;punct对应ctype_punct,可打印的标点符号space对应ctype_space,除了空白字符,还包括缩进,垂直制表符,换行符,回车和换页字符;upper对应ctype_upper,大写字符检测;xdigit对应ctype_xdigit,十六进制字符串[A-Fa-f0-9];filter_var验证: 包括emailipintegerurlmacAddrfloat- 正则验证
regex:\d{6}2.32 判断图像类型
getImageType()方法
- 参数:
string $image 图像路径
- 返回:
false|int 源码:如下
protected function getImageType($image){if (function_exists('exif_imagetype')) {return exif_imagetype($image);}try {$info = getimagesize($image);return $info ? $info[2] : false;} catch (\Exception $e) {return false;}}
说明:
exif_imagetype()通过读取一个图像的第一个字节并检查其签名,并返回图像类型;getimagesize()返回图像信息,索引2是图像类型的标记和exif_imagetype()相同,exif_imagetype更快;2.33 验证表单令牌
token()方法
- 参数:
mixed $value 字段的值string $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function token($value, string $rule, array $data): bool{$rule = !empty($rule) ? $rule : '__token__';return $this->request->checkToken($rule, $data);}
说明:
- 参数:
mixed $value 字段的值string $rule 验证规则
- 返回:
bool 源码:如下
public function activeUrl(string $value, string $rule = 'MX'): bool{if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) {$rule = 'MX';}return checkdnsrr($value, $rule);}
说明:
- 参数:
mixed $value 字段的值string $rule 验证规则
- 返回:
bool 源码:如下
public function ip($value, string $rule = 'ipv4'): bool{if (!in_array($rule, ['ipv4', 'ipv6'])) {$rule = 'ipv4';}return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);}
说明:
- 参数:
\think\File $file 待检测的长传文件string|array $ext 允许后缀 如:['jpeg', 'png']或'jpeg,png'
- 返回:
bool 源码:如下
protected function checkExt(File $file, $ext): bool{if (is_string($ext)) {$ext = explode(',', $ext);}return in_array(strtolower($file->extension()), $ext);}
2.37 检测上传文件大小
checkSize()方法参数:
\think\File $file 待检测的上传文件int $size 文件最大大小
- 返回:
bool 源码:如下
protected function checkSize(File $file, $size): bool{return $file->getSize() <= (int) $size;}
2.38 检测上传文件MIME类型
checkMime()方法参数:
\think\File $file 待检测的长传文件string|array $mime 允许后缀 如:['image/jpeg', 'image/gif']或'image/jpeg,image/gif'
- 返回:
bool 源码:如下
protected function checkMime(File $file, $mime): bool{if (is_string($mime)) {$mime = explode(',', $mime);}return in_array(strtolower($file->getMime()), $mime);}
2.39 验证上传文件后缀
fileExt()方法参数:
\think\File $file 待检测的长传文件mixed $rule 验证规则
- 返回:
bool 源码:如下
public function fileExt($file, $rule): bool{if (is_array($file)) {foreach ($file as $item) {if (!($item instanceof File) || !$this->checkExt($item, $rule)) {return false;}}return true;} elseif ($file instanceof File) {return $this->checkExt($file, $rule);}return false;}
说明:
- 参数:
\think\File $file 待检测的长传文件mixed $rule 验证规则
- 返回:
bool 源码:如下
public function fileMime($file, $rule): bool{if (is_array($file)) {foreach ($file as $item) {if (!($item instanceof File) || !$this->checkMime($item, $rule)) {return false;}}return true;} elseif ($file instanceof File) {return $this->checkMime($file, $rule);}return false;}
说明:
- 参数:
\think\File $file 待检测的长传文件mixed $rule 验证规则
- 返回:
bool 源码:如下
public function fileSize($file, $rule): bool{if (is_array($file)) {foreach ($file as $item) {if (!($item instanceof File) || !$this->checkSize($item, $rule)) {return false;}}return true;} elseif ($file instanceof File) {return $this->checkSize($file, $rule);}return false;}
说明:
- 参数:
\think\File $file 待检测的长传文件mixed $rule 验证规则
- 返回:
bool 源码:如下
public function image($file, $rule): bool{if (!($file instanceof File)) {return false;}if ($rule) {$rule = explode(',', $rule);[$width, $height, $type] = getimagesize($file->getRealPath());if (isset($rule[2])) {$imageType = strtolower($rule[2]);if ('jpg' == $imageType) {$imageType = 'jpeg';}if (image_type_to_extension($type, false) != $imageType) {return false;}}[$w, $h] = $rule;return $w == $width && $h == $height;}return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]);}
说明:
- 参数:
mixed $vlaue 待验证数据mixed $rule 验证规则
- 返回:
bool 源码:如下
public function dateFormat($value, $rule): bool{$info = date_parse_from_format($rule, $value);return 0 == $info['warning_count'] && 0 == $info['error_count'];}
说明:
- 规则可与是
dateFormat:y-m-d; date_parse_from_format()说明见php官网。2.44 验证是否唯一
unique()方法
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据string $field 字段名
- 返回:
bool 源码:如下 ```php public function unique($value, $rule, array $data = [], string $field = ‘’): bool { if (is_string($rule)) {
$rule = explode(',', $rule);
}
if (false !== strpos($rule[0], ‘\‘)) {
// 指定模型类$db = new $rule[0];
} else {
$db = $this->db->name($rule[0]);
}
$key = $rule[1] ?? $field; $map = [];
if (strpos($key, ‘^’)) {
// 支持多个字段验证$fields = explode('^', $key);foreach ($fields as $key) {if (isset($data[$key])) {$map[] = [$key, '=', $data[$key]];}}
} elseif (isset($data[$field])) {
$map[] = [$key, '=', $data[$field]];
} else {
$map = [];
}
$pk = !empty($rule[3]) ? $rule[3] : $db->getPk();
if (is_string($pk)) {
if (isset($rule[2])) {$map[] = [$pk, '<>', $rule[2]];} elseif (isset($data[$pk])) {$map[] = [$pk, '<>', $data[$pk]];}
}
if ($db->where($map)->field($pk)->find()) {
return false;
}
return true; }
- **说明**1. 规则可以是`unique:table,field,except,pk`- **用法示例**```php// 表示验证name在name字段的值是否在user表(不包含前缀)中唯一'name' => 'unique:user',// 表示用User模型验证name在account字段中唯一'name' => 'unique:\\User,account'// 验证其他字段'name' => 'unique:user,account',// 排除某个主键值'name' => 'unique:user,account,10',// 指定某个主键值排除'name' => 'unique:user,account,10,user_id',// 多个字段验证唯一验证条件'name' => 'unique:user,status^account',// 复杂验证条件'name' => 'unique:user,status=1&account='.$data['account'],
2.45 使用filter_var方式验证 filter() 方法
- 参数:
mixed $value 字段的值string $rule 验证规则
- 返回:
bool 源码:如下
public function filter($value, $rule): bool{if (is_string($rule) && strpos($rule, ',')) {[$rule, $param] = explode(',', $rule);} elseif (is_array($rule)) {$param = $rule[1] ?? null;$rule = $rule[0];} else {$param = null;}return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);}
filter_var()参看php手册2.46 验证某个字段等于某个值的时候必须
requireIf()方法参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function requireIf($value, $rule, array $data = []): bool{[$field, $val] = explode(',', $rule);if ($this->getDataValue($data, $field) == $val) {return !empty($value) || '0' == $value;}return true;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function requireCallback($value, $rule, array $data = []): bool{$result = call_user_func_array([$this, $rule], [$value, $data]);if ($result) {return !empty($value) || '0' == $value;}return true;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function requireWith($value, $rule, array $data = []): bool{$val = $this->getDataValue($data, $rule);if (!empty($val)) {return !empty($value) || '0' == $value;}return true;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function requireWithout($value, $rule, array $data = []): bool{$val = $this->getDataValue($data, $rule);if (empty($val)) {return !empty($value) || '0' == $value;}return true;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function in($value, $rule): bool{return in_array($value, is_array($rule) ? $rule : explode(',', $rule));}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function notIn($value, $rule): bool{return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function between($value, $rule): bool{if (is_string($rule)) {$rule = explode(',', $rule);}[$min, $max] = $rule;return $value >= $min && $value <= $max;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function notBetween($value, $rule): bool{if (is_string($rule)) {$rule = explode(',', $rule);}[$min, $max] = $rule;return $value < $min || $value > $max;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function length($value, $rule): bool{if (is_array($value)) {$length = count($value);} elseif ($value instanceof File) {$length = $value->getSize();} else {$length = mb_strlen((string) $value);}if (is_string($rule) && strpos($rule, ',')) {// 长度区间[$min, $max] = explode(',', $rule);return $length >= $min && $length <= $max;}// 指定长度return $length == $rule;}
说明
- 规则可以是
length:1,10length:10; - 验证数据是数组,验证的是数组项个数;数据是文件,验证的时文件长度;数据是字符串,验证的是字符串长度。
2.65 验证数据最大长度
maxLength()方法
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function max($value, $rule): bool{if (is_array($value)) {$length = count($value);} elseif ($value instanceof File) {$length = $value->getSize();} else {$length = mb_strlen((string) $value);}return $length <= $rule;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function min($value, $rule): bool{if (is_array($value)) {$length = count($value);} elseif ($value instanceof File) {$length = $value->getSize();} else {$length = mb_strlen((string) $value);}return $length >= $rule;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function after($value, $rule, array $data = []): bool{return strtotime($value) >= strtotime($rule);}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function before($value, $rule, array $data = []): bool{return strtotime($value) <= strtotime($rule);}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function afterWith($value, $rule, array $data = []): bool{$rule = $this->getDataValue($data, $rule);return !is_null($rule) && strtotime($value) >= strtotime($rule);}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则array $data 验证数据
- 返回:
bool 源码:如下
public function beforeWith($value, $rule, array $data = []): bool{$rule = $this->getDataValue($data, $rule);return !is_null($rule) && strtotime($value) <= strtotime($rule);}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function expire($value, $rule): bool{if (is_string($rule)) {$rule = explode(',', $rule);}[$start, $end] = $rule;if (!is_numeric($start)) {$start = strtotime($start);}if (!is_numeric($end)) {$end = strtotime($end);}return time() >= $start && time() <= $end;}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function allowIp($value, $rule): bool{return in_array($value, is_array($rule) ? $rule : explode(',', $rule));}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function denyIp($value, $rule): bool{return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));}
说明
- 参数:
mixed $value 字段的值mixed $rule 验证规则
- 返回:
bool 源码:如下
public function regex($value, $rule): bool{if (isset($this->regex[$rule])) {$rule = $this->regex[$rule];} elseif (isset($this->defaultRegex[$rule])) {$rule = $this->defaultRegex[$rule];}if (is_string($rule) && 0 !== strpos($rule, '/') && !preg_match('/\/[imsU]{0,4}$/', $rule)) {// 不是正则表达式则两端补上/$rule = '/^' . $rule . '$/';}return is_scalar($value) && 1 === preg_match($rule, (string) $value);}
说明
- 规则可以是
regex:\d{6}或者直接\d{6}; - 正则表到式中含有
|符号时,必须用数组方式定义; - 可以在验证器类中定义
regex属性,正则表达式可以直接调用; - 默认的正则表达式有
alphaalphaNumalphaDashchschsAlphachsAlphaNumchsDashmobileidCardzip。2.75 获取错误信息
getError()方法
- 参数:无
- 返回:
mixed 源码:如下
public function getError(){return $this->error;}
2.76 获取验证规则的错误提示信息
getRuleMsg()方法参数:
string $attribute 字段英文名string $title 字段描述名string $type 验证规则名称
mixed $rule 验证规则
- 返回:
string|array 源码:如下
protected function getRuleMsg(string $attribute, string $title, string $type, $rule){if (isset($this->message[$attribute . '.' . $type])) {$msg = $this->message[$attribute . '.' . $type];} elseif (isset($this->message[$attribute][$type])) {$msg = $this->message[$attribute][$type];} elseif (isset($this->message[$attribute])) {$msg = $this->message[$attribute];} elseif (isset($this->typeMsg[$type])) {$msg = $this->typeMsg[$type];} elseif (0 === strpos($type, 'require')) {$msg = $this->typeMsg['require'];} else {$msg = $title . $this->lang->get('not conform to the rules');}if (is_array($msg)) {return $this->errorMsgIsArray($msg, $rule, $title);}return $this->parseErrorMsg($msg, $rule, $title);}
说明:
- 参数:
string $msg 错误信息
mixed $rule 验证规则string $title 字段描述
- 返回:
string 源码:如下
protected function parseErrorMsg(string $msg, $rule, string $title){if (0 === strpos($msg, '{%')) {$msg = $this->lang->get(substr($msg, 2, -1));} elseif ($this->lang->has($msg)) {$msg = $this->lang->get($msg);}if (is_array($msg)) {return $this->errorMsgIsArray($msg, $rule, $title);}if (is_scalar($rule) && false !== strpos($msg, ':')) {// 变量替换if (is_string($rule) && strpos($rule, ',')) {$array = array_pad(explode(',', $rule), 3, '');} else {$array = array_pad([], 3, '');}$msg = str_replace([':attribute', ':1', ':2', ':3'],[$title, $array[0], $array[1], $array[2]],$msg);if (strpos($msg, ':rule')) {$msg = str_replace(':rule', (string) $rule, $msg);}}return $msg;}
2.78 错误信息数组处理
errorMsgIsArray()方法参数:
string $msg 错误信息mixed $rule 验证规则string $title 字段描述
- 返回:
array 源码:如下
protected function errorMsgIsArray(array $msg, $rule, string $title){foreach ($msg as $key => $val) {if (is_string($val)) {$msg[$key] = $this->parseErrorMsg($val, $rule, $title);}}return $msg;}
2.79 动态方法
__call()public function __call($method, $args){if ('is' == strtolower(substr($method, 0, 2))) {$method = substr($method, 2);}array_push($args, lcfirst($method));return call_user_func_array([$this, 'is'], $args);}
3. 助手函数
3.1 生成验证对象
validate()函数参数:
string|array $validate 验证器类名|验证规则数组array $message 错误提示信息bool $batch 是否批量验证bool $failException 是否抛出异常
- 返回:
Validate 源码:如下
function validate($validate = '', array $message = [], bool $batch = false, bool $failException = true): Validate{if (is_array($validate) || '' === $validate) {$v = new Validate();if (is_array($validate)) {$v->rule($validate);}} else {if (strpos($validate, '.')) {// 支持场景[$validate, $scene] = explode('.', $validate);}$class = false !== strpos($validate, '\\') ? $validate : app()->parseClass('validate', $validate);$v = new $class();if (!empty($scene)) {$v->scene($scene);}}return $v->message($message)->batch($batch)->failException($failException);}
