关于Nest 重写class-validator自定义验证器类

        最近很是烦躁,有一个问题,Nest本身是没有自己的校验的规则的,它依赖的是class-validator,这玩意有很多的内置的校验装饰器,可以在dto中进行使用,但是有一个问题,那就是,这玩意没有结合数据库数据,例如我们想要用户注册的时候校验我们的数据库,保证用户的唯一性,完了它没有...

        怎么办?

        我也是小白,所以我就给大家提供一下我的思路哈

        首先,我想,他不就是个包吗,直接npm上看看去,这里其实也有他的github的地址,你也可以去github上看,我们去吧,npm 翻译成中文,他连代码都给你翻译了......

来到github,你可以使用谷歌翻译,翻译一下,反正我是看不懂

这里有它的目录,从安装到高阶,都有使用的方法哈

这里我们看到了,他自己提供了很多的验证装饰器,但是就是没有我们验证用户唯一性的,所以,我们直接看它的自定义验证类以及自定义验证装饰器哈

就从这里开始,一眼就能看出来了.所以我们自己写一个吧

项目配置

  1. 提前搭建一个nest项目
  2. 配置prisma连接数数据库
  3. 使用docker创建数据库
  4. 创建一个auth模块资源,包含控制器,服务,模块以及dto

我的目录如下,这些是我们必须的内容哈

 

自定义验证类

我们在common里的validators文件中写我们的自定义的验证类

这里我们依照官方的文档自己写一下哈

必须的内容:

  1. 完全实现ValidatorConstraintInterface接口的validate方法
  2. 使用@ValidatorConstraint装饰器标记了我们的自定义类
  3. 我们的dto验证的那个字段,validate的第一个参数就是什么,这里我们使用name(使用prisma中的findUnique方法,必须保证我们的name字段在数据库中是唯一的)
  4. 注入parsma服务,用来在数据库中查询数据
  5. 配置默认消息,避免开发者不传递错误信息

有人会问,我们的

args: ValidationArguments是什么?

其实这个就是我们的当前的dto的信息哈,它包含我们当前的数据,字段名.dto等信息

// is-user-already-exist.validator.ts
import { ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';
import { PrismaService } from '../../../prisma/prisma.service';
import { Injectable } from '@nestjs/common';

@ValidatorConstraint({ async: true })
@Injectable()
export class IsUserAlreadyExist implements ValidatorConstraintInterface {

  // 这里我们拿到prisma,获取用户
  constructor(private readonly prisma: PrismaService) {
  }

  // 传一个name即可
  async validate(name: string, args: ValidationArguments) {
    console.log(`你现在验证的用户是${args.value}`);

    // 查询用户
    const user = await this.prisma.user.findUnique({
      where: {
        name,
      },
    });

    return !user;// true 表示验证通过(即不存在),false 表示验证失败(存在)
  }

  // 配置默认消息
  defaultMessage(args: ValidationArguments): string {
    return `User with name ${args.value} already exists`;
  }
}

其实到这里,我们写的自定义验证类已经可以使用了

我们只需要把他注入到module的providers中,然后再dto中使用即可,注意,你只能使用

@Validate(IsUserAlreadyExist)的格式,不可以使用 @IsUserAlreadyExist,因为你还没有把他封装为装饰器呢
@Validate(IsUserAlreadyExist)

 当你使用的时候,你会发现用不了,这里就是我踩的坑了,原因是什么?就是你官当文档没有看完呗

你直接使用我们的自定义验证类是无法使用的,他会提示错译,意思就是无法获取到user,意思就是他拿不到prisma服务了,为什么?因为他不在nest的IOC内,所以,你看文档提示的

这里才是最关键的 

自定义验证装饰器

如何直接封装为装饰器呢?官方也给出了答案,所以我们直接爪照抄

 核心部分:

  1. 暴露一个函数,函数名作为装饰器名
  2. 接收ValidationOptions作为参数,这是必须的,否则你无法使用
    validationOptions的错误信息等
  3. validator必须使用我们刚刚写的自定义验证类
import { registerDecorator, ValidationOptions } from 'class-validator';
import { IsUserAlreadyExist } from '../validators/is-user-already-exist.validator';

export function IsUserAlreadyExistDecorator(validationOptions?: ValidationOptions) {
  return function(object: object, propertyName: string) {
    registerDecorator({
      name: 'IsUserAlreadyExist',
      target: object.constructor,
      propertyName,
      options: validationOptions,
      validator: IsUserAlreadyExist,
    });
  };
}

其实到这里还没有结束,因为我们这个装饰器和自定义验证类之只能服务于我们的name校验,那么email校验呢?其他的唯一性校验呢?所以请期待一下我们的通用唯一性装饰器,其实也很简单 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值