🔷

もう技術選定や設計に悩まない!?全部入りフルスタックTypeScriptフレームワークAdonisJS - バリデーション編

2025/02/28に公開

前回の記事では、AdonisJSのLucid ORMを使用したデータベース操作について解説しました。マイグレーションの作成、モデルの定義、コントローラでのデータ操作方法を学び、データベースとアプリケーションを連携させる基本を押さえました。

今回は、バリデーション(データ検証) について詳しく解説します。アプリケーションにおいて、ユーザーからの入力を適切に検証することは、セキュリティやデータの整合性を保つ上で非常に重要です。AdonisJS v6 では、バリデーションライブラリとして VineJS が標準で組み込まれており、追加のインストールや設定は不要です。VineJSを活用することで、型安全なスキーマバリデーションを簡単に実装できます。

1. VineJSとは?

VineJSは、AdonisJS v6に統合されたバリデーションライブラリであり、スキーマベースのバリデーションを提供します。入力データの整形やカスタムバリデーションルールの作成にも対応しており、安全で堅牢なデータ処理を実現できます。

また、高速なバリデーションを実現するために最適化されています。公式のベンチマークによると、VineJSはZodやYupといった他のバリデーションライブラリと比較して、より優れたパフォーマンスを発揮します。

このパフォーマンスの高さにより、大量のリクエストが発生する環境でも、スムーズなデータ処理が可能になります。

https://vinejs.dev/

2. バリデータの作成

AdonisJSでは、バリデータをコマンドで作成できます。以下のコマンドを実行すると、app/validators/ ディレクトリ内にバリデーションファイルが生成されます。

node ace make:validator post

これにより、app/validators/post.ts が作成されます。

バリデータの定義

バリデーションスキーマでは、vine.object({...}) を使ってデータの形式を定義し、それぞれのフィールドに適切なルールを適用します。例えば、vine.string().trim().minLength(6) は、文字列をトリム(前後の空白を削除)し、最低6文字以上であることを保証します。vine.string().trim().escape() は、文字列内のHTMLエンティティをエスケープします。

import vine from '@vinejs/vine'

/**
 * Postのcreateアクションをバリデーションします
 */
export const createPostValidator = vine.compile(
  vine.object({
    title: vine.string().trim().minLength(6),
    content: vine.string().trim().escape()
  })
)

/**
 * Postのupdateアクションをバリデーションします
 */
export const uupdatePostValidator= vine.compile(
  vine.object({
    title: vine.string().trim().minLength(6),
    content: vine.string().trim().escape()
  })
)

https://adonisjs-docs-ja.vercel.app/guides/basics/validation#バリデータの作成

3. コントローラでバリデーションを適用

コントローラ内で request.validateUsing() を使用することで、リクエストデータに対してバリデーションを適用できます。これにより、クライアントからの不正なデータを事前にフィルタリングし、アプリケーションの安定性やセキュリティを強化できます。

バリデーションが成功すると、リクエストデータが処理され、データベースに保存されます。逆に、バリデーションに失敗した場合は 422 Unprocessable Entity のレスポンスが自動的に返され、適切なエラーメッセージがクライアントに通知されます。

import type { HttpContext } from '@adonisjs/core/http'
import Post from '#models/post'
import { createPostValidator, updatePostValidator } from '#validators/post'

export default class PostsController {
  async store({ request, response }: HttpContext) {
    const data = await request.validateUsing(createPostValidator)
    const post = await Post.create(data)
    return response.json(post)
  }

  async update({ params, request, response }: HttpContext) {
    const post = await Post.findOrFail(params.id)
    const data = await request.validateUsing(updatePostValidator)
    post.merge(data)
    await post.save()
    return response.json(post)
  }
}

4. バリデーションの動作確認

バリデーションエラーの例(タイトルが短すぎる)

curl -X POST http://localhost:3333/posts \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"title": "short", "content": "Test content"}' | jq

レスポンス例:

{
  "errors": [
    {
      "message": "The title field must have at least 6 characters",
      "rule": "minLength",
      "field": "title",
      "meta": {
        "min": 6
      }
    }
  ]
}

成功例

curl -X POST http://localhost:3333/posts \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"title": "Valid Title", "content": "This is valid content."}' | jq

成功レスポンス例:

{
  "title": "Valid Title",
  "content": "This is valid content.",
  "createdAt": "2025-02-27T14:36:33.004+00:00",
  "updatedAt": "2025-02-27T14:36:33.004+00:00",
  "id": 7
}

5. まとめ

この記事では、AdonisJS v6のVineJSを使用したバリデーション処理の実装方法について解説しました。
次回はフロントエンド(Inertia + React)側の実装について解説します!

Fusic 技術ブログ

Discussion