Валидация с VineJS
Данным из формы нельзя доверять: заголовок могут оставить пустым, а в поле числа прислать текст. Валидация — проверка входящих данных по правилам до того, как они попадут в базу. В AdonisJS для этого используют библиотеку VineJS: правила описываются схемой, а результат проверки получает точные типы TypeScript.
Создание валидатора
node ace make:validator postПоявится файл app/validators/post.ts. Опишите правила для новой статьи:
// app/validators/post.ts
import vine from '@vinejs/vine'
export const createPostValidator = vine.compile(
vine.object({
title: vine.string().trim().minLength(3).maxLength(255),
body: vine.string().trim().minLength(10),
})
)vine.object описывает ожидаемые поля, vine.string() требует строку, а trim, minLength и maxLength уточняют правила. vine.compile один раз превращает схему в быструю функцию проверки. По умолчанию все поля обязательны.
Проверка в контроллере
// app/controllers/posts_controller.ts
import type { HttpContext } from '@adonisjs/core/http'
import Post from '#models/post'
import { createPostValidator } from '#validators/post'
export default class PostsController {
async store({ request, response }: HttpContext) {
const payload = await request.validateUsing(createPostValidator)
const post = await Post.create(payload)
return response.redirect().toRoute('posts.show', { id: post.id })
}
}validateUsing берёт данные запроса и проверяет их. Если всё верно, payload содержит только описанные поля с типом { title: string; body: string }. Лишние поля, например isAdmin, в него не попадут.
Что происходит при ошибке
Если проверка не прошла, код после validateUsing не выполняется. Дальше AdonisJS действует по типу запроса:
| Запрос | Ответ |
|---|---|
| Обычная HTML-форма | Редирект назад, ошибки и введённые значения сохраняются в сессии |
JSON-запрос (заголовок Accept: application/json) | Статус 422 и JSON со списком ошибок |
Как показать ошибки рядом с полями формы, разобрано в следующем уроке.
Частые правила
| Правило | Что проверяет |
|---|---|
vine.string().email() | Адрес почты |
vine.number().min(1) | Число не меньше 1 |
vine.boolean() | Да или нет, в том числе флажок формы |
vine.enum(['draft', 'published']) | Одно из значений |
vine.string().optional() | Поле можно не передавать |
vine.string().confirmed() | Совпадение с полем ..._confirmation |
Сообщения на русском
Стандартные сообщения VineJS — на английском. Свои тексты задают провайдером сообщений. Создайте файл предзагрузки командой node ace make:preload validator и запишите в него:
// start/validator.ts
import vine, { SimpleMessagesProvider } from '@vinejs/vine'
vine.messagesProvider = new SimpleMessagesProvider({
'required': 'Поле {{ field }} обязательно',
'minLength': 'Поле {{ field }} должно быть не короче {{ min }} символов',
'title.minLength': 'Заголовок слишком короткий',
})Ключ title.minLength задаёт сообщение для одного поля и одного правила, а общий minLength — для всех остальных.
Частая ошибка
Валидатор создают внутри метода контроллера: const validator = vine.compile(...) прямо в store. Тогда схема компилируется заново при каждом запросе, и это заметно замедляет приложение. Объявляйте валидаторы в app/validators/ на верхнем уровне модуля, а в контроллер импортируйте готовые.