表单验证简介

未匹配的标注

AdonisJS 对请求体的 解析验证 有一流的支持,无需安装第三方包,只需定义验证声明并根据它验证请求体。

import Route from '@ioc:Adonis/Core/Route'
import { schema } from '@ioc:Adonis/Core/Validator'

Route.post('posts', async ({ request }) => {
  /**
   * Schema definition
   */
  const newPostSchema = schema.create({
    title: schema.string(),
    body: schema.string(),
    categories: schema.array().members(schema.number()),
  })

  /**
   * 根据声明验证请求正文
   */
  const payload = await request.validate({ schema: newPostSchema })
})

验证器还从声明定义中 提取静态类型,您可以从单个声明定义中获得运行时验证和静态类型安全性。

Schema composition

声明定义分为三个主要部分。

  • schema.create 方法定义了您期望的数据的形状。
  • schema.string, schema.number,和其他类型方法定义单个字段的数据类型。
  • 最后,您使用 rules 对象在给定字段上应用额外的验证约束,例如:验证字符串是否为有效电子邮件并在数据库中是唯一的。

注:rules 对象是从 @ioc:Adonis/Core/Validator 导入的。

import { schema, rules } from '@ioc:Adonis/Core/Validator'

如果您仔细看,我们将 格式验证核心数据类型 分开,例如,没有称为 schema.email 的数据类型,我们使用 rules.email 方法来确保字符串格式化为电子邮件。

这种分离有助于使用自定义规则扩展验证器,而不会创建不必要的模式类型。例如,没有所谓的 email type;它只是一个字符串,格式为电子邮件。

使用可选值和 null

默认情况下,所有字段都是必填。但是,可以使用optionalnullablenullableAndOptional 修饰符将字段标记为可选和可空。

所有这些修饰符都有不同的用途,详情如下:

修饰符 验证行为 返回结果
optional 允许 nullundefined 值同时存在 返回值中对应项可以不存在
nullable 允许存在 null 值。但是,该字段必须在验证数据中存在声明 返回包含 null 的字段值
nullableAndOptional 允许 nullundefined 值同时存在。 (与修饰符 1 相同) 仅当值未定义时不返回键,否则返回字段值

nullable 修饰符

你经常会发现自己使用 nullable 修饰符来允许在表中使用可选字段。

在以下示例中,当用户为 fullName 字段提交空值时,服务器将收到 null ,因此你可以将数据库中现有的全名更新为 null。

schema: schema.create({
  fullName: schema.string.nullable(),
})

nullableAndOptional 修饰符

如果你创建的 API 服务器接受 PATCH 请求并允许客户端更新资源的一部分,则必须使用 nullableAndOptional 修饰符。

在下面的例子中,如果 fullName 是未定义的,你可以假设客户端不想更新这个属性,如果是 null,他们则想要设置属性值 null

const payload = await request.validate({
  schema: schema.create({
    fullName: schema.string.nullableAndOptional(),
  })
})

const user = await User.findOrFail(1)
user.merge(payload)
await user.save()

optional 修饰符

optional 修饰符在你想要更新没有任何可选字段资源的一部分时很有用。

email 属性在以下示例中可能存在也可能不存在。但是用户不能设置它为 null。如果该属性不在请求中,你将不会更新邮件字段。

const payload = await request.validate({
  schema: schema.create({
    email: schema.string.optional(),
  })
})

const user = await User.findOrFail(1)
user.merge(payload)
await user.save()

验证 HTTP 请求

您可以使用 request.validate 方法验证给定 HTTP 请求的请求正文、查询字符串和路由参数。如果失败,validate 方法将抛出异常。

import Route from '@ioc:Adonis/Core/Route'
import { schema, rules } from '@ioc:Adonis/Core/Validator'

Route.post('users', async ({ request, response }) => {
  /**
   * 第 1 步 - 定义架构
   */
  const newUserSchema = schema.create({
    username: schema.string(),
    email: schema.string([
      rules.email()
    ]),
    password: schema.string([
      rules.confirmed(),
      rules.minLength(4)
    ])
  })

  try {
    /**
     * 第 2 步 - 验证架构下的请求正文
     */
    const payload = await request.validate({
      schema: newUserSchema
    })
  } catch (error) {
    /**
     *  第 3 步 - 处理错误
     */
    response.badRequest(error.messages)
  }
})

我们建议 不要自行处理 异常而是让 AdonisJS 使用内容协商转换异常 到响应正文。

以下是内容协商如何工作的说明。

服务器渲染

如果你使用服务器端模板构建标准 Web 应用程序,我们会将客户端重定向回表单并将错误作为会话闪存消息传递。

以下是会话闪存存储中错误消息的结构。

{
  errors: {
    username: ['username is required']
  }
}

你可以使用 flashMessages 进行全局访问。

@if(flashMessages.has('errors.username'))
  <p> {{ flashMessages.get('errors.username') }} </p>
@end

带有 Accept=application/json 请求头的请求

协商 JSON 数据类型的请求以对象数组的形式接收错误消息,每条错误消息都包含字段名称、失败的验证规则错误消息

{
  errors: [
    {
      field: 'title',
      rule: 'required',
      message: 'required validation failed',
    },
  ]
}

JSON API

使用 Accept=application/vnd.api+json 请求头协商的请求,根据 JSON API 规范 接收错误消息。

{
  errors: [
    {
      code: 'required',
      source: {
        pointer: 'title',
      },
      title: 'required validation failed'
    }
  ]
}

单独使用验证器

你还可以通过从 Validator 模块导入 validate 方法在 HTTP 请求之外使用验证器。功能 API 保持不变。但是,你必须手动提供 data 进行验证。

import { validator, schema } from '@ioc:Adonis/Core/Validator'

await validator.validate({
  schema: schema.create({
    // ... 定义结构
  }),
  data: {
    email: 'virk@adonisjs.com',
    password: 'secret'
  }
})

此外,由于你在 HTTP 请求之外执行验证,因此必须手动处理异常并显示错误。

验证器类

验证器类允许您从控制器中提取内联模式并将它们移动到专用类。

您可以通过执行以下 Ace 命令来创建新的验证器。

node ace make:validator CreateUser

# 创建: app/Validators/CreateUserValidator.ts

所有与验证相关的属性,包括 schemamessages 都被定义为类的属性。

// title: app/Validators/CreateUserValidator.ts
import { schema, CustomMessages } from '@ioc:Adonis/Core/Validator'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class CreateUserValidator {
  constructor (protected ctx: HttpContextContract) {
  }

  public schema = schema.create({
  })

  public messages: CustomMessages = {}
}

使用验证器

您现在可以将类构造函数传递给 request.validate 方法,而不是传递具有 schema 属性的对象。

import Route from '@ioc:Adonis/Core/Route'
// highlight-start
import CreateUser from 'App/Validators/CreateUserValidator'
// highlight-end

Route.post('users', async ({ request, response }) => {
  // highlight-start
  const payload = await request.validate(CreateUser)
  // highlight-end
})

在验证期间,会在后台创建验证器类的实例,此外,request.validate 方法会将当前 HTTP 上下文作为第一个构造函数参数传递。

您还可以手动构造类实例并传递您喜欢的任何参数,例如:

Route.post('users', async ({ request, response }) => {
  const payload = await request.validate(
    new CreateUser({
      countries: fetchAllowedCountries(),
      states: fetchAllowedStates()
    })
  )
})

以下是在 HTTP 请求之外使用验证器类的示例。

import { validator } from '@ioc:Adonis/Core/Validator'
import CreateUser from 'App/Validators/CreateUserValidator'

await validator.validate(
  new CreateUser({
    countries: fetchAllowedCountries(),
    states: fetchAllowedStates()
  })
)

下一步是什么?

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/va...

译文地址:https://learnku.com/docs/adonisjs/5.x/va...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~