ThinkPHP5 验证器的具体使用


Posted in PHP onMay 31, 2018

前言:

我们在做API开发的时候,我们会接受客户端传来的参数,大家都知道这个参数是不可信的,我们后端开发人员必须对这个参数进行验证。我在之前的开发中只是知道tp5的验证器,并不知道他的用途,因为之前的开发验证,往往都是基于模型字段进行的验证。而验证器更适用与API开发,今天就简单讲下验证器的使用

目录:

  1. 创建验证器
  2. 书写单独验证器
  3. 调用验证

1.创建验证器

首先我们需要一个文件夹来存放我们的验证器,我们在模块下创建一个同控制器平级的文件夹,取名为validate

ThinkPHP5 验证器的具体使用

然后我们就可以来建立验证器了,我们只需要创建一个类,继承tp5的validate类就可以了。

但是熟悉面向对象思想的朋友一定知道,当我们需要一个方法每个验证器都要用到,但是又不去修改tp5的源码时。我们就多写一个类来作为我们的基类。所有的验证器都继承这个基类,然后这个基类再去继承tp5的validate类。

这里我们把他取名为baseValidate

ThinkPHP5 验证器的具体使用

那么现在再创建一个正儿八经的验证器了。举个例子:

namespace app\index\validate;

use think\Validate;

class User extends Validate
{
  protected $rule = [
    'name' => 'require|max:25',
    'email' => 'email',
  ];

}

再到控制器或者模型中去实例化再调用

//虚拟一组数据,实际开发中是接受用户传递的数据
$data = [
  'name'=>'thinkphp',
  'email'=>'thinkphp@qq.com'
];

$validate = Loader::validate('User');

if(!$validate->check($data)){
  dump($validate->getError());
}

这样一个验证器的应用就写好了。我们来看看有没有什么可以简化的地方。

  1. 首先需要被验证的数据是我们从客户端那接受过来的那么,第一步接受数据
  2. 然后我们要对数据进行验证,如果验证不通过,返回错误信息

这两部是每次接口被请求都是要做的。那么我们就想把这个封装到BaseValidate中去

namespace app\home\validate;
use think\Exception;
use think\Request;
use think\Validate;
class BaseValidate extends Validate
{
  public function goCheck($data='')
  {
    //实例化请求对象
    $requestObj=Request::instance();
    //如果传入为空则获取请求里的参数
    empty($data)&&$data=$requestObj->param();
    if ($this->check($data)) {
      //如果验证通过了
      return true;
    }else{
      //如果验证没通过
      $error=$this->getError();
      //抛出异常
      throw new Exception($error);
    }
  }
}

这个goCheck方法封装好后,有人可能会问,这个验证规则在哪里呢?

2. 书写单独验证器

之前有说过BaseValidate是用来被继承的,那么真正的验证器,我们还没有开始写。规则就制定到这个验证器中。为了更深入的理解,这里举例子顺便使用了自定义验证 规则。其实tp写好了的验证规则应该很够用了

我们就拿最常接受的数据来举例子,那就是 id 同常这个id就代表了我们数据库中某条数据的id,这个id我们往往设计为无符号自动递增的主键,翻译成人话就是正整数。那么如果客户传来的参数是负数或者小数那么就不应该通过验证。

我们根据上述需求,我们来创建一个验证器。位置还是跟之前的一样在validate文件夹下

ThinkPHP5 验证器的具体使用

取名为IdMustBePositiveInt.php(名字有点长,不过好在望文知意)

首先肯定是要继承我们的基础验证器

class IdMustBePositiveInt extends BaseValidate

然后制定规则,为一个固定的成员变量赋值

protected $rule = [
  //require是内置规则,而tp5并没有正整数的规则,所以下面这个positiveInt使用自定义的规则
    'id' => 'require|positiveInt'
  ];

那么自定义规则怎么干呢,其实也简单。定义一个被保护的方法

//系统会自动传入几个参数 第一个是 要验证的值,第二个是规则,自己可以规定规则内容或者不写,第三个是最初传入的data。其实不只这三个参数,想了解详细的可以看看文档
 protected function positiveInt($value, $rule='', $data)
  {
    if (is_int(($value+0))&&($value+0)>0) {
      return true;
    }else{
      return 'id必须为正整数';
    }
  }

!!注意:这里如果判断失败:返回的不是false 返回的是错误信息。

3. 调用验证

根据我们之前的封装,我们需要达到的效果就是接受参数,验证参数一体。那么现在我们如何调用验证呢

厉害的来了,我们还是以id为例

public function test($id)
  {
    //在控制器中直接调用写上这行代码就搞定验证了
    (new IdMustBePositiveInt)->goCheck();
  }
  1. 就这样的一句代码,直接搞定验证。当我们实例化id验证器,调用它父类的goCheck方法。
  2. goCheck方法会接受参数,并且将参数传入validate对象上check方法
  3. 就会去匹配我们在id验证器中$rule中规定的require规则和我们自定义的规则。
  4. 如果都通过就会返回true
  5. 如果其中一条不匹配则会抛出异常

这次只举了id为例子,虽然看上去比直接写独立验证麻烦很多,但是大家仔细想想,这个验证规则其实在很多地方都是一样的,比如密码验证规则,用户名验证规则等,当这个项目写完了。你已经完成了很多验证器。其实在下个项目中还可以继续套用的哦

TP5验证规则使用

①静态调用(使用内置的规则验证单个数据,返回值为布尔值)

// 日期格式验证
Validate::dateFormat('2016-03-09','Y-m-d'); // true
// 验证是否有效的日期
Validate::is('2016-06-03','date'); // true
// 验证是否有效邮箱地址
Validate::is('thinkphp@qq.com','email'); // true
// 验证是否在某个范围
Validate::in('a',['a','b','c']); // true
// 验证是否大于某个值
Validate::gt(10,8); // true
// 正则验证
Validate::regex(100,'\d+'); // true

②模型验证(在模型中的验证方式)

$User = new User;
$result = $User->validate(
  [
    'name' => 'require|max:25',
    'email'  => 'email',
  ],
  [
    'name.require' => '名称必须',
    'name.max'   => '名称最多不能超过25个字符',
    'email'    => '邮箱格式错误',
  ]
)->save($data);
if(false === $result){
  // 验证失败 输出错误信息
  dump($User->getError());
}

③控制器验证(控制器中进行验证)

如果你需要在控制器中进行验证,并且继承了\think\Controller的话,可以调用控制器类提供的validate方法进行验证,如下:

$result = $this->validate(
  [
    'name' => 'thinkphp',
    'email' => 'thinkphp@qq.com',
  ],
  [
    'name' => 'require|max:25',
    'email'  => 'email',
  ]);
if(true !== $result){
  // 验证失败 输出错误信息
  dump($result);
}

控制器中的验证代码可以简化为:

$result = $this->validate($data,'User');
if(true !== $result){
  // 验证失败 输出错误信息
  dump($result);
}

如果要使用场景,可以使用:

$result = $this->validate($data,'User.edit');
if(true !== $result){
  // 验证失败 输出错误信息
  dump($result);
}

在validate方法中还支持做一些前置的操作回调,使用方式如下:

$result = $this->validate($data,'User.edit',[],[$this,'some']);
if(true !== $result){
  // 验证失败 输出错误信息
  dump($result);
}

好了,本次tp5验证器的介绍了就写到这里了,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
分页显示Oracle数据库记录的类之二
Oct 09 PHP
PHP新手上路(十一)
Oct 09 PHP
PHP 长文章分页函数 带使用方法,不会分割段落,翻页在底部
Oct 22 PHP
PHP 飞信好友免费短信API接口开源版
Jul 22 PHP
PHP三元运算符的结合性介绍
Jan 10 PHP
PHP命名空间(Namespace)的使用详解
May 04 PHP
PHP 只允许指定IP访问(允许*号通配符过滤IP)
Jul 08 PHP
PHP进程同步代码实例
Feb 12 PHP
php支付宝手机网页支付类实例
Mar 04 PHP
如何实现php图片等比例缩放
Jul 28 PHP
ThinkPHP中create()方法自动验证表单信息
Apr 28 PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 PHP
php 截取中英文混合字符串的方法
May 31 #PHP
PHP封装curl的调用接口及常用函数详解
May 31 #PHP
PHP通过curl获取接口URL的数据方法
May 31 #PHP
php获得刚插入数据的id 的几种方法总结
May 31 #PHP
PHP+MySQL使用mysql_num_rows实现模糊查询图书信息功能
May 31 #PHP
PHP实现可精确验证身份证号码的工具类示例
May 31 #PHP
JSON PHP中,Json字符串反序列化成对象/数组的方法
May 31 #PHP
You might like
php与flash as3 socket通信传送文件实现代码
2014/08/16 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
2020/04/14 PHP
网站如何做到完全不需要jQuery也可以满足简单需求
2013/06/27 Javascript
JavaScript中的单引号和双引号报错的解决方法
2014/09/01 Javascript
吐槽一下我所了解的Node.js
2014/10/08 Javascript
javascript实现继承的简单实例
2015/07/26 Javascript
jQuery实现的图片轮播效果完整示例
2016/09/12 Javascript
浅谈原型对象的常用开发模式
2017/07/22 Javascript
原生JS上传大文件显示进度条 php上传文件代码
2020/03/27 Javascript
最简单的JS实现json转csv的方法
2019/01/10 Javascript
手把手15分钟搭一个企业级脚手架
2019/09/16 Javascript
vue导航栏部分的动态渲染实例
2019/11/01 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
JavaScript事件循环及宏任务微任务原理解析
2020/09/02 Javascript
js定时器出现第一次延迟的原因及解决方法
2021/01/04 Javascript
python从入门到精通(DAY 2)
2015/12/20 Python
python 列表,数组,矩阵两两转换tolist()的实例
2018/04/04 Python
Python实现针对给定字符串寻找最长非重复子串的方法
2018/04/21 Python
python实现ID3决策树算法
2018/08/29 Python
使用EduBlock轻松学习Python编程
2018/10/08 Python
python selenium 弹出框处理的实现
2019/02/26 Python
Python自定义函数计算给定日期是该年第几天的方法示例
2019/05/30 Python
python3实现raspberry pi(树莓派)4驱小车控制程序
2020/02/12 Python
Python使用docx模块实现刷题功能代码
2020/02/13 Python
Python基于gevent实现高并发代码实例
2020/05/15 Python
CSS3自定义滚动条样式的示例代码
2017/08/21 HTML / CSS
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
命名空间(namespace)和程序集(Assembly)有什么区别
2015/09/25 面试题
优秀学生干部个人事迹材料
2014/06/02 职场文书
建筑安全标语
2014/06/07 职场文书
上课随便讲话检讨书
2014/09/12 职场文书
中韩经贸翻译专业大学生职业生涯规划范文
2014/09/18 职场文书
专题组织生活会思想汇报
2014/10/01 职场文书
寻找成龙观后感
2015/06/12 职场文书
Python编解码问题及文本文件处理方法详解
2021/06/20 Python
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android