如何使用class-validator在nest js中添加唯一字段验证

问题描述 投票:0回答:2

如何使用类验证器在 Nest JS 中进行数据库验证(例如唯一字段验证)?

我创建了一个自定义验证类并尝试了它。但是当我在验证函数中控制台记录该服务时,

userService
未定义。

import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
import { Injectable } from '@nestjs/common';
import { UserService } from './user.service';

@ValidatorConstraint({ name: 'unique', async: true })
@Injectable()
export class UniqueFieldValidator implements ValidatorConstraintInterface {
  constructor(private readonly userService: UserService) {
  }

  validate = async (value: any, args: ValidationArguments): Promise<boolean> => {
    console.log(this.userService); // <-- This log prints undefined
    const [entityClass, fieldName] = args.constraints;
    const entity = await this.userService.findByFieldValue({ [fieldName]: value });
    return !entity;
  }

  defaultMessage(args: ValidationArguments) {
    const [entityClass, fieldName] = args.constraints;
    return `${fieldName} must be unique`;
  }
}

我在侧

createUserDto
类中调用了这个类,如下所示。

import { IsEnum, IsNotEmpty, MinLength, Validate } from "class-validator";
import { CompanyStatuses } from "src/company/dto/company.enums";
import { User } from "../entities/user.entity";
import { UniqueFieldValidator } from "../unique-field-validator";

export class CreateUserDto {

    @IsNotEmpty()
    @MinLength(3)
    @Validate(UniqueFieldValidator, [User, 'username'])
    username: string
}

UniqueFieldValidator
班级调用成功。 但由于当我发送创建用户的请求时,验证函数中未定义
userServices
,因此它返回错误消息:

    TypeError: Cannot read properties of undefined (reading 'findByFieldValue')
    at UniqueFieldValidator.validate

如果有人在 NestJs 中使用类验证器经历过这种情况,请帮助我。谢谢!

附注

下面的代码显示了我如何编写我的 userModule,并且我已将 UserService 和 Validator 类添加到 Providers 数组中。还将 @injectable() 装饰器放置在 UserService 类的顶部。但它仍然不起作用。

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UniqueFieldValidator } from './unique-field-validator';

@Module({
  controllers: [UserController],
  providers: [UserService,UniqueFieldValidator],
  imports: [TypeOrmModule.forFeature([User])],
  exports: [UserService,TypeOrmModule]
})
export class UserModule { }
javascript typescript validation nestjs class-validator
2个回答
3
投票

是啊!我找到了一个解决方案并将其发布到我自己的问题中,以帮助将来遇到此问题的人。 只需在您的 root 方法中添加

useContainer(app.select(AppModule), { fallbackOnErrors: true });
即可。

然后我的

main.ts
就这样了

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { useContainer } from 'class-validator';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  useContainer(app.select(AppModule), { fallbackOnErrors: true });
  await app.listen(3000);
}
bootstrap();

我将其发布到我自己的问题中以帮助将来的某人。


0
投票

首先请忽略上面的答案。您需要创建 isUnique 类:

import { Injectable } from '@nestjs/common'
import { ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator'
import { EntityManager } from 'typeorm'

@ValidatorConstraint({ name: 'IsUniqueConstraint', async: true })
@Injectable()
export class IsUnique implements ValidatorConstraintInterface {
  constructor(private readonly entityManager: EntityManager) {}
  async validate(value: any, args?: ValidationArguments): Promise<boolean> {
    const [tableName, column] = args?.constraints as string[]

    const dataExist = await this.entityManager
      .getRepository(tableName)
      .createQueryBuilder(tableName)
      .where({ [column]: value })
      .getExists()

    return !dataExist
  }

  defaultMessage(validationArguments: ValidationArguments): string {
    const field = validationArguments.property

    return `${field} is already exist.`
  }
}

然后你应该去 AppModule 并添加 IsUnique 作为提供者

@Module({
  imports: [ConfigModule.forRoot(), TypeOrmModule.forRoot(DATABASE_CONFIG), UsersModule],
  providers: [ IsUnique],
})
export class AppModule {}

最后如何使用它:

export class CreateUserDto {
  @IsAlphanumeric()
  @MinLength(3, { message: 'Username must have atleast 3 characters.' })
  @Validate(IsUnique, ['users', 'username'])
  username!: string

最终配置将是 bootstrap 方法中 main.ts 中的这个

  useContainer(app.select(AppModule), { fallbackOnErrors: true })
© www.soinside.com 2019 - 2024. All rights reserved.