如何使用类验证器在 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 { }
是啊!我找到了一个解决方案并将其发布到我自己的问题中,以帮助将来遇到此问题的人。 只需在您的 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();
我将其发布到我自己的问题中以帮助将来的某人。
首先请忽略上面的答案。您需要创建 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 })