校验规则
BetterValidate 校验规则
类校验
对于参数的校验,Lin 提供了类校验这种便捷,好用的方式,它会 对ctx.request.body(上下文请求体)
、ctx.request.query(上下文请求query参数)
、ctx.request.header(上下文请求头)
、ctx.param(路由参数)
这些参数进行统一校验 ,所以请保证你的参数名没有重复。
代码演示:
class RegisterValidator extends LinValidator {
constructor() {
super();
this.nickname = [
new Rule("isNotEmpty", "昵称不可为空"),
new Rule("isLength", "昵称长度必须在2~10之间", 2, 10)
new Rule("isInt", "分组id必须是整数,且大于0", { min: 1 })
];
this.group_id = new Rule("isInt", "分组id必须是整数,且大于0", {
min: 1
});
this.email = [
new Rule("isOptional"),
new Rule("isEmail", "电子邮箱不符合规范,请输入正确的邮箱")
];
this.password = [
new Rule(
"matches",
"密码长度必须在6~22位之间,包含字符、数字和 _ ",
/^[A-Za-z0-9_*&$#@]{6,22}$/
)
];
this.confirm_password = new Rule("isNotEmpty", "确认密码不可为空");
}
validateConfirmPassword(data) {
if (!data.body.password || !data.body.confirm_password) {
return [false, "两次输入的密码不一致,请重新输入"];
}
let ok = data.body.password === data.body.confirm_password;
if (ok) {
return ok;
} else {
return [false, "两次输入的密码不一致,请重新输入"];
}
}
}
isOptional
isOptional
这个 Rule 校验, 当字段存在时,则校验,不存在则不校验
new Rule("isOptional", "", "pedrogao1996@gmail.com"),
当isOptional
Rule 被赋有默认值时,这个字段就会发生变化。以email
为例,当前端没 有传入这个参数时,校验器中的email
数据肯定是一个undefined
。但是因为默认值的存 在,这个email
会被赋予默认值,即pedrogao1996@gmail.com
自定义规则函数
规则函数是校验器中另一种用于对参数校验的方式,它比显示的 Rule 校验具有更加的灵活 性和可操作性。下面我们以一个小例子来深入理解规则函数:
validateConfirmPassword(data) {
if (!data.body.password || !data.body.confirm_password) {
return [false, "两次输入的密码不一致,请重新输入"];
}
let ok = data.body.password === data.body.confirm_password;
if (ok) {
return ok;
} else {
return [false, "两次输入的密码不一致,请重新输入"];
}
}
首先任何一个规则函数,满足以validate
开头的类方法,除validate()
这个函数外。都 会被带入一个重要的参数data
。data 是前端传入参数的容器,它的整体结构如下:
this.data = {
body: ctx.request.body, // body -> body
query: ctx.request.query, // query -> query
path: ctx.params, // params -> path
header: ctx.request.header // header -> header
};
返回值的所有可选项类似如下:
validateNameAndAge() {
// 表示校验成功
return true;
// 校验失败,并给定错误信息
return [false,"message"]
// 校验失败,并给定错误信息,以及错误信息的键为nameAndAge
// 一般情况下,我们会默认生成键,如这个函数生成的键为 NameAndAge,当然你也可以选择自定义
return [false,"message","nameAndAge"]
}
规则函数除了通过返回值来判断失败之外,还可以通过抛出异常来提前结束规则函数并校验 失败。如下:
validateNameAndAge() {
// 抛出异常,即校验失败
throw new ParametersException({ msg: "Lin will carry you!" });
// 返回true,表示校验成功
return true;
}
这两种方式都可以使规则函数校验失败,但是我们推荐你使用第一种方式,即返回值方 式
继承
校验器提供继承的方式,让你的参数可以被组合校验。
class PositiveIdValidator extends LinValidator {
constructor() {
super();
this.id = new Rule("isInt", "id必须为正整数", { min: 1 });
}
}
我们首先定义了一个PositiveIdValidator
的校验器,它会被 id 这个参数进行正整数校 验,一般情况下 id 的校验被使用的很普遍,其他的校验器也需要使用,但是我们又不想重 新再写一遍。因此,我们可以继承PositiveIdValidator
。
class UpdateUserInfoValidator extends PositiveIdValidator {
constructor() {
super();
this.group_id = new Rule("isInt", "分组id必须是正整数", {
min: 1
});
this.email = new Rule("isEmail", "电子邮箱不符合规范,请输入正确的邮箱");
}
}
这里UpdateUserInfoValidator
继承了PositiveIdValidator
,因 此UpdateUserInfoValidator
也可对 id 参数进行校验,而且扩展了 group_id 和 email 两个参数的校验。
别名
validator 不仅仅提供继承,还提供另一种解放劳动力的方式——别名。如:
class PositiveIdValidator extends LinValidator {
constructor() {
super();
this.id = new Rule("isInt", "id必须为正整数", { min: 1 });
}
}
PositiveIdValidator
会对 id 参数进行校验,但是有时候参数的校验逻辑是一样的,但 是参数的名字不相同。如 uid 这个参数,它跟 id 这个参数的 Rule 一样。那么我们是不 是还需要重新再写一个校验器定义一个 uid 的 Rule 了。这可行,但不优雅。
const v = await new PositiveIdValidator().validate(ctx, { id: "uid" });
我们可以通过上面的方式来给 id 一个别名,这个别名为 uid。当使用了别名之后,校验器 不会对 id 这个参数做校验,但是会对 uid 这个参数做校验。