浅谈TP5验证器

永远不要相信前端传输的数据,一定要进行验证,TP5有两种验证方式独立验证与验证器

独立验证

独立验证就是在操作方法中实例Validate对数据进行验证

<?php

namespace app\index\controller;

use think\Request;
use think\Validate;

class Index
{
    /**
     * 独立验证
     * @param Request $request
     */
    public function index(Request $request)
    {
        $id    = $request->param('id');
        $email = $request->param('email');
        $data  = [
            'id'    => $id,
            'email' => $email,
        ];
        $rule = [
            'id'=>'require|number|max:2',
            'email'=>'require|email'
        ];
        $msg = [
            'id.require'    => 'id为必填项',
            'id.max'        => 'id最大不能超过99',
            'email.require' => 'email邮箱为必填项',
            'email.email'   => 'email邮箱格式不正确',
        ];
        $field = [
            'id'    => '自增编号',
            'email' => '邮箱',
        ];
        $validate = new Validate($rule,$msg,$field);
        if( ! $validate->batch()->check($data) ){
            $error = $validate->getError();
            dump($error);exit;
        };
    }
}

直接在controller中使用unique

文档太简陋了,还要看源码才行,‘name’ => ‘unique:user,status=1&account=’.$data[‘account’],这种的只能放在controller中,自己来定义rule和message,在单独的validate类中无法将相关的值传递过去。
规则是:unique:【模型类名(或表名)】,【要验证的字段(或者包含=号或者包含^号,但是必须把本身的条件加入,别以为前面有name了就不把name本身加进去了)】,【要排除的字段】,【主键(可不填)】

<?php

namespace app\index\controller;

use think\Validate;
use think\Request;

class Index
{
    /**
     *  验证器验证
     */
    public function index(Request $request)
    {
        $id = $request->post('id');
		$shopId = session('shop_id');
		$name = $request->post('name');
		$sort = $request->post('sort', 0, 'intval');
		$postData = [
		    'name' => $name,
		    'sort' => $sort
		];
		$rule = [
		    'name' => 'require|unique:ArticleCategory,shop_id=' . $shopId . '&name=' . $name,//名称
		    'sort' => 'number'
		];
		$message = [
		    'name.require' => '分类名称必须填写',
		    'name.unique' => '分类名称已存在',
		    'sort.number' => '排序必须填写整数',
		];
		$validate = new Validate($rule, $message);
		if (!empty($id)) {
		    $validate->scene('edit',
		        [
		            'sort',
		            'name' => 'require|unique:ArticleCategory,shop_id=' . $shopId . '&name=' . $name . ',' . $id
		        ]);
		    $validateRes = $validate->scene('edit')->check($postData);
		} else {
		    $validate->scene('add', ['sort', 'name']);
		    $validateRes = $validate->scene('add')->check($postData);
		}
		if (true !== $validateRes) {
		    $data['msg'] = $validate->getError();
		    return json($data);
		}
    }
}

验证器

新建Validate子类,并定义验证规则,错误信息提示,场景等。然后再控制器中进行调用

简单版

<?php
namespace app\validate;

class UserValidate extends BaseValidate
{
    // 验证器规则和提示信息合并显示
   protected $rule = [
         ['username',"require|length:2,10","用户名不存在2|用户名只2-10位字符之间2"],
         ['password',"require|length:2,10","需要输入密码2|密码需要保持2-10位字符2"],
   ];
 
   // 设置验证场景
   protected $scene = [
        'login'  =>  ['username','password'],
   ];
}

场景使用

<?php

namespace app\index\controller;

use app\validate\UserValidate;
use think\Request;

class Index
{
    /**
     *  验证器验证
     */
    public function index(Request $request)
    {
        $data = [
            'name' => 'zs',
            'age' => 'zs',
            'email' => '[email protected]',
        ];
        $validate = new UserValidate();
        $res = $validate->scene('add')->batch()->check($data);
        if( ! $res ){
            $error = $validate->getError();
            dump($error);exit;
        }
    }
}

//下面是独立的验证器
namespace app\validate;

use think\Validate;

class UserValidate extends Validate
{
    protected $rule = [
        'name'  => 'require|max:25',
        'age'   => 'require|positiveInteger|between:18,120',
        'email' => 'require|email',
    ];

    protected $message = [
        'name.require' => '名称必须',
        'name.max'     => '名称最多不能超过25个字符',
        'age.number'   => '年龄必须是数字',
        'age.between'  => '年龄只能在1-120之间',
        'email'        => '邮箱格式错误',
    ];

    protected $field = [
        'name'  => '姓名',
        'age'   => '年龄',
        'email' => '邮箱',
    ];

    protected $scene = [
        'edit' => [
            'name',
            'email',
        ],
        'add' => [
            'name',
            'age',
            'email',
        ],
    ];

    /**
     * 自定义验证规则
     * @param $value string 验证数据
     * @param $rule string 验证规则
     * @param $data array 全部数据
     * @param $field string 字段名
     * @param $fieldDesc string 字段描述
     * @return bool|string
     */
    public function positiveInteger($value,$rule,$data,$field,$fieldDesc)
    {
        if( is_numeric($value) && is_int($value + 0) && ($value + 0) > 0 ) return true;
        return $field.'必须是正整数';
    }
}

利用AOP思想的验证器

  • 首先创立一个基类验证器

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

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

namespace app\validate;

use app\lib\exception\ParameterException;
use think\Request;
use think\Validate;

class BaseValidate extends Validate
{

    /**
     * 检测客户端发来的参数是否符合验证类参数
     * @return bool
     * @throws ParameterException
     */
    public function goCheck()
    {
        $request = Request::instance();
        $params  = $request->param();

        if( ! $this->batch()->check($params) ){
            $error = $this->error;
            if( is_array($error) ){
                $error = implode(';',$error);
            }
            throw new ParameterException(['msg' => $error]);
        }
        return true;
    }

    /**
     * 判断是否是正整数
     * 系统会自动传入几个参数
     * 第一个是 要验证的值
     * 第二个是规则自己可以规定规则内容或者不写
     * 第三个是最初传入的data
     * 其实不只这三个参数,想了解详细的可以看看文档
     * @param $value
     * @param $rule
     * @param $data
     * @param $field
     * @param $fieldDesc
     * @return bool|string
     */
    protected function isPositiveInteger($value, $rule, $data, $field,$fieldDesc)
    {
        if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0) {
            return true;
        }
        return $field . '必须是正整数';
    }
}
  • 然后再建立一个派生类
namespace app\validate;

class UserValidate extends BaseValidate
{
    protected $rule = [
        'name'  => 'require|max:25',
        //require是内置规则,而tp5并没有正整数的规则,所以下面这个isPositiveInteger使用自定义的规则
        'age'   => 'require|isPositiveInteger|between:18,120',
        'email' => 'require|email',
    ];
}
  • 使用验证器
public function test($id)
{
    //在控制器中直接调用写上这行代码就搞定验证了
    (new UserValidate)->goCheck();
	// todo 后续的逻辑
	return json('验证通过',200);
}

就这样的一句代码,直接搞定验证。
当我们实例化id验证器,调用它父类的goCheck方法。
goCheck方法会接受参数,并且将参数传入validate对象上check方法
就会去匹配我们在id验证器中$rule中规定的require规则和我们自定义的规则。
如果都通过就会返回true。
如果其中一条不匹配则会抛出异常。

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

参考文章:https://www.jianshu.com/p/1fb961dcab7f

发布了4 篇原创文章 · 获赞 1 · 访问量 584

猜你喜欢

转载自blog.csdn.net/m1ssyAn/article/details/104502030