💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ### 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 这个参数做校验**。