葛胖胖的小草屋 一言不合 rm -fr /

tp5.1利用中间件实现API开发实现自动校验参数及自定义异常处理

2019-01-07
cossete

阅读:

PHP

tp5.1利用中间件实现API开发实现自动校验参数及自定义异常处理

在接口开发中免不了参数校验,利用tp中间件可以更好的解耦参数校验。平时开发中初级写法如下:

<?php 
/**
 *初级写法
 **/
namespace app\index\user;
public function register()
{
    $request = request();
    $params  = $request->param();
    if (empty($params['user_name'])) {
        return json(['code' => -1, 'msg' => '请输入账号']);
    }
    if (!preg_match('/^[a-z0-9]$/i', $params['user_name'])) {
        return json(['code' => -1, 'msg' => '账号只能是英文和数字']);
    }
    if (empty($params['password'])) {
        return json(['code' => -1, 'msg' => '请输入密码']);
    }
    //todo ...各种判断通过后 再进行实际的业务逻辑
}

这种写法不灵活,万一修改为xml返回,则需要劳师动众,下面利用TP验证器来简化代码

namespace app\test\validate;
use think\Validate;
class User extends Validate
    protected $rule = [
        'user_name' => 'require|alphaNum',
        'password'  => 'require|checkPwd',
    ];

    protected $message = [
        'user_name.require'  => '请输入账号',
        'user_name.alphaNum' => '账号只能是数字和字母',
        'password.require'   => '请输入密码',
    ];
    protected $scene = [
        'login'    => ['user_name', 'password'],
        'register' => ['user_name', 'password'],
    ];
	
	/**
	 *自定义校验方法,不能为private
	 */
	protected function checkPwd($value)
    {
        var_dump($value);
        return true;
    }
<?php 
/**
 *中级写法
 **/
namespace app\test\user;
public function register()
{
    $request  = request();
    $params   = $request->param();
    $validate = new \app\test\validate\User;

    if (!$validate->scene('register')->check($params)) {
        return json(['code' => -1, 'msg' => $validate->getError()]);
    }
    //todo ...再进行实际的业务逻辑
}

这样在controller层就减少一大片各种判断,当接口越来越多的时候,代码可能会如下

<?php 
namespace app\test\user;

public function register()
{
    $request  = request();
    $params   = $request->param();
    $validate = new \app\test\validate\User;
    if (!$validate->scene('register')->check($params)) {
        return json(['code' => -1, 'msg' => $validate->getError()]);
    }
    //todo ...再进行实际的业务逻辑
}
public function login()
{
    $request  = request();
    $params   = $request->param();
    $validate = new \app\test\validate\User;
    if (!$validate->scene('login')->check($params)) {
        return json(['code' => -1, 'msg' => $validate->getError()]);
    }
    //todo ...再进行实际的业务逻辑
}
//还有无数个接口

这样看起来不是很优雅,要是有100个接口岂不每个方法面前都是类似的代码。利用TP中间件能够在执行每个方法之前都自动判断参数和规则

//首先我们在 application/test/middleware 目录中创建 中间件文件 Validate.php
<?php

namespace app\test\middleware;

use think\Controller;

class Validate extends Controller
{
    /**
     * 默认返回资源类型
     * @var \think\Request $request
     * @var mixed $next
     * @var string $name
     * @throws \Exception
     * @return mixed
     */
    public function handle($request, \Closure $next, $name)
    {
        //获取当前参数
        $params = $request->param();
        //获取访问模块
        $module = $request->module();
        //获取访问控制器
        $controller = ucfirst($request->controller());
        //获取操作名,用于验证场景scene
        $scene    = $request->action();
        $validate = "app\\" . $module . "\\validate\\" . $controller;
        //仅当验证器存在时 进行校验
        if (class_exists($validate)) {
            $v = $this->app->validate($validate);
            if ($v->hasScene($scene)) {
                //仅当存在验证场景才校验
                $result = $this->validate($params, $validate . '.' . $scene);
                if (true !== $result) {
                    //校验不通过则抛出异常,留后面自定义异常获取
                    throw new ValidateException($result);
                }
            }
        }
        return $next($request);
    }
}

然后在application\test 目录下 新建middleware.php

<?php
// 中间件扩展定义文件
return [
    'validate'  => app\test\middleware\Validate::class
];

最终,在控制器中的代码我们可以简化成如下:

<?php 
/**
 *高级写法
 **/
namespace app\test\user;

public function register()
{
    $request  = request();
    $params   = $request->param();
    //todo ...此时校验已经通过,可直接进行实际的业务逻辑
}
public function login()
{
    $request  = request();
    $params   = $request->param();
    //todo ...此时校验已经通过,可直接进行实际的业务逻辑
}
//更多其他接口

自定义异常

在上述校验过程中校验失败会抛出异常,此时我们采用自定义异常处理

原文出处

吸取别人长处


Similar Posts

Comments