自定义验证规则
你可以使用 validator.rule
方法向验证器添加自定义规则。规则只能注册一次。因此,我们建议你在服务提供商或 预加载文件 中注册它们。
在本指南中,我们将它们保存在 start/validator.ts
文件中。你可以通过运行以下 Ace 命令来创建此文件,并将环境选择为 “HTTP 服务器期间”。
node ace make:prldfile validator
打开新创建的文件并将以下代码粘贴到其中。
// title: start/validator.ts
import { string } from '@ioc:Adonis/Core/Helpers'
import { validator } from '@ioc:Adonis/Core/Validator'
validator.rule('camelCase', (value, _, options) => {
if (typeof value !== 'string') {
return
}
if (value !== string.camelCase(value)) {
options.errorReporter.report(
options.pointer,
'camelCase',
'camelCase validation failed',
options.arrayExpressionPointer
)
}
})
validator.rule
方法接受规则名称作为第一个参数。- 第二个参数是规则实现。该函数接收验证中的字段值、规则选项和表示模式树的对象。
在上面的示例中,我们创建了一个 camelCase
规则来检查字段值是否与其 camelCase 版本相同。如果没有,我们将使用 errorReporter 类实例报告错误。
使用规则#
在使用你的自定义规则之前,你必须通知 TypeScript 编译器。否则,它会抱怨规则不存在。
为了通知 TypeScript,我们将使用 declaration merging 并将属性添加到 Rules
接口。
在路径 contracts/validator.ts
处创建一个新文件 (文件名不重要) 并将以下内容粘贴到其中。
// title: contracts/validator.ts
declare module '@ioc:Adonis/Core/Validator' {
interface Rules {
camelCase(): Rule
}
}
完成后,你可以从 rules
对象访问 camelCase
规则。
// highlight-start
import { rules, schema, validator } from '@ioc:Adonis/Core/Validator'
// highlight-end
await validator.validate({
schema: schema.create({
fileName: schema.string({}, [
// highlight-start
rules.camelCase()
// highlight-end
]),
}),
data: {},
})
将选项传递给规则#
规则也可以接受选项,它们将作为第二个参数提供给验证回调。
这次让我们从 TypeScript 接口开始,定义我们期望从规则使用者那里得到的选项。
// title: contracts/validator.ts
declare module '@ioc:Adonis/Core/Validator' {
interface Rules {
camelCase(maxLength?: number): Rule
}
}
传递给规则函数的所有参数都可以作为规则实现的数组使用。因此,例如,你可以访问 maxLength
选项,如下所示。
validator.rule('camelCase', (
value,
// highlight-start
[maxLength],
// highlight-end
options
) => {
// Rest of the validation
if (maxLength && value.length > maxLength) {
options.errorReporter.report(
options.pointer,
// highlight-start
'camelCase.maxLength', // 👈 注意这个
// highlight-end
'camelCase.maxLength validation failed',
options.arrayExpressionPointer,
{ maxLength }
)
}
})
最后,如果你注意到,我们将规则名称作为 camelCase.maxLength
传递给错误报告器。这将允许用户为 maxLength
定义自定义验证消息。
messages: {
'camelCase.maxLength': 'Only {{ options.maxLength }} characters are allowed'
}
规范化选项#
很多时候,你希望规范化传递给验证规则的选项。例如:在用户未提供时使用默认的 maxLength
。
我们建议你在编译阶段只对它们进行一次规范化,而不是规范化验证回调中的选项。
validator.rule
方法接受一个回调函数作为第三个参数,并在编译阶段运行它。
validator.rule(
'camelCase', // 规则名称
() => {}, // 验证回调
// highlight-start
([maxLength]) => {
return {
compiledOptions: {
maxLength: maxLength || 10,
},
}
}
// highlight-end
)
然后将 compiledOptions
值作为第二个参数传递给验证回调。根据上面的示例,验证回调将接收 maxLength
作为对象。
validator.rule(
'camelCase', // 规则名称
// highlight-start
(value, { maxLength }) => {}, // 验证回调
// highlight-end
([maxLength]) => {
return {
compiledOptions: {
maxLength: maxLength || 10,
},
}
}
)
异步规则#
要优化验证过程,你必须明确告知验证器您的验证规则本质上是异步的。只需从编译回调中返回 async: true
,然后您就可以在验证回调中使用 async/await
。
validator.rule(
'camelCase', // 规则名称
// highlight-start
async () => {}, // 验证回调
// highlight-end
() => {
return {
// highlight-start
async: true,
// highlight-end
compiledOptions: {},
}
}
)
限制规则对特定数据类型起作用#
在编译回调中,你可以访问应用了验证规则的字段的 schema type/subtype ,然后有条件地允许它仅用于特定类型。
以下是将 camelCase
规则限制为仅字符串模式类型的示例。
validator.rule(
'camelCase', // 规则名称
async () => {}, // 验证回调
(options, type, subtype) => {
if (subtype !== 'string') {
throw new Error('"camelCase" rule can only be used with a string schema type')
}
return {
compiledOptions: {},
}
}
)
如果有人尝试对非字符串字段使用 camelCase
规则,则会引发异常。
schema: schema.create({
fileName: schema.number([
rules.camelCase() // 会导致运行时出错
]),
}),
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。