校验规则

优质
小牛编辑
130浏览
2023-12-01

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"),

isOptionalRule 被赋有默认值时,这个字段就会发生变化。以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 这个参数做校验