验证规则
基于Webmozart Assert封装的验证,利用反射简化了原有的调用过程,增加了语言包,自定义验证规则
基本使用
//验证规则
$rule = [
//字符串方式 '验证的字段'=>'规则1|规则2:参数1|规则3:参数1:参数2'
'category_num' =>'notEmpty|eq:10|lengthBetween:1:3',
//数组方式
'category_name' => [ //验证的字段
'notEmpty',//规则1
'eq' => [ //规则2
10, //参数1
],
'lengthBetween' => [ //规则3
1, //参数1
3, //参数2
],
],
];
//自定义message,如果没有自定义,就默认读语言包的
$msg =[
'category_num.notEmpty'=>'必填'
];
//调用验证
(new Validator())->v($this->in, $rule);
复制代码
语言包
语言包文件是lang/zh-cn.php(框架自带或者任意配置文件)
'notEmpty' => '请填写%s', //%s代表替换字段
'eq' => '', 如果默认消息为空,可以自定义添加
复制代码
自定义验证规则
在Ext目录下新建或者在已有的trait里新增方法方法名必须是唯一的,不能跟现有的重复,方法名即验证规则
trait Test
{
//第一个参数,必须是$val,这个参数就是字段的值,最后一个参数必须是$message 就是消息,中间可以自定义参数,没有限制个数
public function testValidator($val,$min,$message='')
{
if($val>0){
throw new \InvalidArgumentException($message);
}
}
}
复制代码
已有的验证规则可以查看github.com/webmozart/a…上面的
反射
是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。 反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用
其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。
本人比较懒就直接贴代码了、、、、、、、
目录结构
.
+-- Validator.class.php
+-- ValidatorExt.class.php
+-- Ext
| +-- Test.class.php
| +-- header.html
复制代码
Validator
<?php
namespace RestfulApi\Common\Validator;
use Webmozart\Assert\Assert;
/**
* 验证
* Class Validator
* @package RestfulApi\Common\Validator
* @author matao
* @since 2018-08-01
*/
class Validator
{
/**
* 验证
* @param $data
* @param $rules
* @param array $msg
* @return bool
* @throws \ReflectionException
* @author matao
* @since 2018-08-01
*/
public function v($datas, $rules, $msg = [])
{
//转化验证规则
$rule = $this->formatRule($rules);
//转化值
$data = $this->conversion($datas, $rules);
//验证
$this->validator($data, $rule, $msg);
return true;
}
/**
* 格式化rule
* @param $rules
* @return array
* @author matao
* @since 2018-08-01
*/
private function formatRule($rules)
{
$rule = [];
foreach ($rules as $key => $value) {
if (is_string($value)) {
$tmp = explode('|', $value);
$currentRule = [];
foreach ($tmp as $t) {
$subRule = explode(':', $t);
if (is_array($subRule) && count($subRule) > 1) {
$K = $subRule[0];
unset($subRule[0]);
$currentRule[$K] = array_values($subRule);
} else {
$currentRule[] = $subRule[0];
}
}
$rule[$key] = $currentRule;
} else {
$rule[$key] = $value;
}
}
return $rule;
}
/**
* data转换
* @param $datas
* @param $rules
* @return array
* @author matao
* @since 2018-08-07
*/
private function conversion($datas, $rules)
{
$allKey = array_keys($rules);
$allKey = array_fill_keys($allKey, null);
return array_merge($allKey, $datas);
}
/**
* 执行验证
* @param $data
* @param $rule
* @param array $msg
* @throws \ReflectionException
* @author matao
* @since 2018-08-01
*/
private function validator($data, $rule, $msg = [])
{
foreach ($data as $key => $datum) {
if (!isset($rule[$key])) {
break;
}
foreach ($rule[$key] as $k => $value) {
if (is_array($value)) {
$param = $value;
array_unshift($param, $datum);
$method = $k;
} else {
$param[] = $datum;
$method = $value;
}
$message = '';
//如果有自定义message就使用
if (!empty($msg["{$key}.{$method}"])) {
$message = $msg["{$key}.{$method}"];
} elseif (L($method)) { //L($method) 是获取方法对应的message
$message = sprintf(L($method), $key); //用当前字段字段替换%s ,%s代表输出的是字符串
}
$param[] = $message ?: ''; //$param是该方法的参数[$val1,$val2]
//调用具体的方法
$this->scheduler($method, $param);
unset($param);
}
}
}
/**
* 调度
* @param $method
* @param $param
* @throws \ReflectionException
* @author matao
* @since 2018-08-01
*/
private function scheduler($method, $param)
{
$base = new Assert();
//没有找到Webmozart Assert里的方法就使用自定义的
if ($this->reflection($base, $method, $param) === false) {
$ext = new ValidatorExt();
$this->reflection($ext, $method, $param);
}
}
/**
* 反射
* @param $class
* @param $method
* @param $param
* @return bool
* @throws \ReflectionException
* @author matao
* @since 2018-08-01
*/
public function reflection($class, $method, $param)
{
//放入要反射的类
$reflectionClass = new \ReflectionClass($class);
//查找是否存在该方法
$isMethod = $reflectionClass->hasMethod($method);
if ($isMethod === true) {
//获取类方法
$reflectionMethod = $reflectionClass->getMethod($method);
//从指定的参数创建一个新的类实例
$reflectionInstance = $reflectionClass->newInstance($param);
//放入参数并调用该方法
$reflectionMethod->invokeArgs($reflectionInstance, $param);
return true;
}
return false;
}
}
复制代码
ValidatorExt 自定义方法
<?php
namespace RestfulApi\Common\Validator;
//自定义验证,方法不能跟已有的重复
use RestfulApi\Common\Validator\Ext\MySQLValidator;
use RestfulApi\Common\Validator\Ext\Test;
class ValidatorExt
{
use Test, MySQLValidator;
public function __construct()
{
}
}
复制代码
testValidator
<?php
namespace RestfulApi\Common\Validator\Ext;
trait Test
{
public function testValidator($val,$message='')
{
if($val>0){
//抛出错误
throw new \InvalidArgumentException($message);
}
}
}
复制代码
捕获抛出的异常
set_exception_handler(function (\InvalidArgumentException $exception) {
##########################随意发挥#############################
});
复制代码