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 ...此时校验已经通过,可直接进行实际的业务逻辑
}
//更多其他接口
自定义异常
在上述校验过程中校验失败会抛出异常,此时我们采用自定义异常处理