## 请求验证器
验证器是为了验证请求参数是否合法,根据需要配置不同的验证器,如果验证不通过会自动返回错误信息。 目录 `app\Requests`
示例:
```php
/**
* 商品列表请求验证
*/
namespace App\Requests\Goods;
use App\Requests\Request;
class GoodsListRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// 'cateid' => [ 'integer', 'min' => 0, 'max' => MYSQL_INT_MAX, 'required' => false, 'default' => 0, 'label' => '商品分类' ],
// 'grade' => [ 'enum', 'options' => [ 1, 2, 3, 4, 5, 6 ], 'required' => true, 'default' => 0, 'label' => '年级' ],
'state' => [ 'enum', 'options' => [ 0, 1 ], 'required' => true, 'default' => 1, 'label' => '获取全部:[0全部,1正常]' ],
'psize' => [ 'integer', 'min' => 1, 'max' => MYSQL_INT_MAX, 'required' => false, 'default' => 20, 'label' => '每页显示条目' ],
'skip' => [ 'integer', 'min' => 1, 'max' => MYSQL_INT_MAX, 'required' => false, 'default' => 0, 'label' => '跳过多少条' ],
'gids' => [ 'string', 'min' => 0, 'max' => 255, 'required' => false, 'default' => '', 'label' => '商品id集合' ],
];
}
}
```
验证器核心代码:
```php
namespace App\Fend\Http;
class FormRequest
{
/**
* 待验证参数
*
* @var array
*/
protected $data = [];
/**
* 安全参数
*
* @var array
*/
protected $safetyData = [];
/**
* 验证规则
*
* @var
*/
protected $rules;
/**
* 错误消息
*
* @var null
*/
protected $errorMessage = [];
/**
* 构造方法
*
* @param array $data
*/
public function __construct($data = [])
{
$this->data = $data;
}
/**
* 请求提示
*
* @return string
*/
public function notes()
{
return '';
}
/**
* 设置数据
*
* @param $data
*/
public function setData($data)
{
$this->data = $data;
}
/**
* 设置规则
*
* @param $rules
*/
public function setRules($rules)
{
$this->rules = $rules;
}
/**
* 获取全部数据
*/
public function all()
{
return $this->safetyData;
}
/**
* 获取验证规则
*
* @return mixed
*/
protected function getRules()
{
if( method_exists($this, 'rules')){
$this->rules = $this->rules();
}
return $this->rules;
}
/**
* 验证参数
*
* @param array $data
* @return bool
*/
public function validate($data = [])
{
if( !empty($data) ){
$this->data = $data;
}
foreach($this->getRules() as $key => $rule){
$this->selectAction(getValue($this->data, $key, null), $key, $rule[0], $rule);
}
return empty($this->errorMessage);
}
/**
* 获取错误信息
*
* @return null
*/
public function getMessage()
{
return $this->errorMessage;
}
/**
* 根据规则类型选择验证方法.
*
* @param $value
* @param $key
* @param $action
* @param $vParams
* @return bool|null
*/
private function selectAction($value, $key, $action, $vParams){
$newValue = $this->run($action,$key,$value,$vParams);
if($newValue === false) {
// 验证失败,记录错误信息
$this->errorMessage[$key] = "`{$key}` params error.";
}else{
$this->safetyData[$key] = addslashes($newValue);
}
return $newValue;
}
/**
* 执行验证
*
* @param $action
* @param $key
* @param $value
* @param $vParams
* @return bool|null
*/
private function run($action,$key,$value,$vParams){
$newValue = null;
switch (strtolower($action)){
case 'required':
$newValue = $this->vRequired($value);
break;
case 'tel':
$newValue = $this->vTel($value,$vParams['required'],$vParams['default']);
break;
case 'uuid':
$newValue = $this->vUuid($value,$vParams['required'],$vParams['default']);
break;
case 'integer':
$newValue = $this->vInteger($value,$vParams['min'],$vParams['max'],$vParams['required'],$vParams['default']);
break;
case 'string':
$newValue = $this->vString($value,$vParams['min'],$vParams['max'],$vParams['required'],$vParams['default']);
break;
case 'array':
$newValue = $this->vArray($value,$vParams['min'],$vParams['max'],$vParams['required'],$vParams['default']);
break;
case 'json':
$newValue = $this->vJson($value,$vParams['required'],$vParams['default']);
break;
case 'email':
$newValue = $this->vEmail($value,$vParams['required'],$vParams['default']);
break;
case 'mobile':
$newValue = $this->vMobile($value,$vParams['required'],$vParams['default']);
break;
case 'match':
$newValue = $this->vMatch($value,$vParams['pattern'],$vParams['required'],$vParams['default']);
break;
case 'enum':
$newValue = $this->vEnum($value,$vParams['options'],$vParams['required'],$vParams['default']);
break;
case 'version':
$newValue = $this->vVersion($value,$vParams['required'],$vParams['default']);
break;
case 'file':
$newValue = $this->vFile($key,$vParams['extensions'],$vParams['min_size'],$vParams['max_size'],$vParams['required'],$vParams['default']);
break;
default:
$this->errorMessage = "`{$action}` Rules Action Undefined.";
break;
}
return $newValue;
}
/**
* 检查参数知否为空
*
* @param $value
* @return bool
*/
protected function vRequired($value){
return !empty($value);
}
/**
* 验证电话号码格式(固定电话)
*
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vTel($value, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if(verify_tel($value)){
return $value;
}
return false;
}
/**
* 验证uuid格式
*
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vUuid($value, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/';
if(preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 验证数字参数范围
*
* @param $value
* @param $min
* @param $max
* @param $required
* @param $default
* @return bool
*/
protected function vInteger($value, $min, $max, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return (int)$value; }
if( is_numeric($value) && ($value >= $min) && ($value <= $max) ){
return $value + 0; // 转换为数字,防止小数未使用(int)
}
return false;
}
/**
* 验证字符串参数长度范围
*
* @param $value
* @param $min
* @param $max
* @param $required
* @param $default
* @return bool
*/
protected function vString($value, $min, $max, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if( is_string($value) && ($len = mb_strlen($value)) && ($len >= $min) && ($len <= $max) ){
return $value;
}
return false;
}
/**
* 验证数组长度
* @param $value
* @param $min
* @param $max
* @param $required
* @param $default
* @return bool
*/
protected function vArray($value, $min, $max, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if( is_array($value) && ($len = count($value)) && ($len >= $min) && ($len <= $max) ){
return $value;
}
return false;
}
/**
* 检查是否是一个合法的 json
*
* @deprecated
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vJson($value, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if(isJson($value)){
return $value;
}
return false;
}
/**
* 验证邮箱格式
*
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vEmail($value, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if(isMail($value)){
return $value;
}
return false;
}
/**
* 验证手机号格式
*
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vMobile($value, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$preg = '#^13[0-9]\d{8}$|^14[0-9]\d{8}|^15[0-9]\d{8}$|^17[0-9]\d{8}$|^18[0-9]\d{8}$#';
return preg_match($preg, $value) ? $value : false;
}
/**
* 版本号验证
*
* @param $value
* @param $required
* @param $default
*
* @return bool
*/
protected function vVersion($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{2}\.[0-9]{2}\.[0-9]{3,6}$/';
if(preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 算法版本号验证
*
* @param $value
* @param $required
* @param $default
*
* @return bool
*/
protected function vVersionByAlgorithm($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{3,6}$/';
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 蓝牙库版本号
*
* @param $value
* @param $required
* @param $default
* @return bool
*/
protected function vVersionByBluetooth($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,6}$/';
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 固件版本号验证
*
* @param $value
* @param $required
* @param $default
*
* @return bool
*/
protected function vVersionByFirmware($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{2}\.[0-9]{2}\.[0-9]+$/';
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* APP版本号验证
*
* @param $value
* @param $required
* @param $default
*
* @return bool
*/
protected function vVersionByApp($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,6}$/';
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 硬件版本号验证
*
* @param $value
* @param $required
* @param $default
*
* @return bool
*/
protected function vVersionByHardware($value,$required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$pattern = '/^[0-9]{2}\.[0-9]{2}$/';
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* 正则验证
*
* @param $value
* @param $pattern
* @param $required
* @param $default
* @return bool
*/
protected function vMatch($value, $pattern, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
if(is_string($value) && preg_match($pattern, $value)){
return $value;
}
return false;
}
/**
* Enum 验证
*
* @param $value
* @param $options
* @param $required
* @param $default
* @return bool
*/
protected function vEnum($value, $options, $required, $default){
if(empty($value) && $required === false){ $value = $default; }
if( !$required && empty($value)){ return $value; }
$options = array_map(function($val){ return (string)$val; }, $options);
if(in_array((string)$value, $options, true)){
return is_numeric($value) ? $value + 0 : $value;
}
return false;
}
/**
* 上传文件验证
*
* @param $paramsKey
* @param $suffix
* @param $min_size
* @param $max_size
* @param $required
* @param $default
* @return bool|mixed|string
*/
protected function vFile($paramsKey, $suffix, $min_size, $max_size, $required, $default){
$storage = getValue($_FILES, $paramsKey);
if( !$required && empty($storage)){ return $storage; } // 检查是否必填项,如果不允许或者有值进入验证
if( empty($storage) ){ return false; } // 检查是否正确
$extension = pathinfo( $storage['name'],PATHINFO_EXTENSION );
if(!in_array($extension, $suffix)){
return false; // 文件类型不对
}
$size = $storage['size'];
if( !($size > $min_size && $size < $max_size) ){
return false; // 文件大小错误
}
return $storage;
}
}
```