バリデーション

リクエストとして送られてくるデータは、開発者が望んだ形式で送られてこないかもしれません。数値を入力すべきフィールドにアルファベットを入力するユーザがいるかもしれません。たとえクライアントサイドのJavascriptで検証するように実装したとしても、リクエストの内容を改ざんするのは簡単なことなので、サーバサイドでその内容を検証する仕組みは必須なのです。

前述のとおり、受信したリクエストデータはハッシュ形式で表現されます(取得方法についてはこちらの章をご覧ください)。通常、リクエストデータをモデルにセットする前に、それぞれの値が正しい形式であるかを検証します。

まず、blog 向けのリクエストデータ(ハッシュ)を検証するバリデーションクラスのスケルトンを生成します。アプリケーションルートに移動して、次のコマンドを実行します。

 $ tspawn validator blog
   created   helpers/blogvalidator.h
   created   helpers/blogvalidator.cpp
   updated   helpers/helpers.pro

生成された BlogValidator クラスのコンストラクタで、バリデーションルールを設定します。例えば、title 変数の文字列の長さが4文字以上20文字以下というルールは、次のように書きます。

BlogValidator::BlogValidator() : TFormValidator()
{
   setRule("title", Tf::MinLength, 4);
   setRule("title", Tf::MaxLength, 20);
}

この第2引数である enum 値として、入力必須、文字列最大長/最小長、整数最大値/最小値、日付形式か、メールアドレス形式か、ユーザ定義ルール(正規表現)などから1つ指定できます (これらは tfnamespace.h に定義されている)。
setRule() の第4引数には、検証エラー時のメッセージを設定することができます。もしメッセージを指定しなければ、config/validation.ini ファイルに定義されたメッセージが設定されます。

「入力必須」のルールについては暗黙的に設定されます。もし「入力必須」でないようにするには、次のように記述します。

setRule("title", Tf::Required, false);

設定可能なルール

説明
Required 入力必須
MaxLength 文字列の最大長
MinLength 文字列の最小長
IntMax 最大値(int)
IntMin 最小値(int)
DoubleMax 最大値(double)
DoubleMin 最小値(double)
EmailAddress Eメールアドレス
Url URL形式
Date 日付形式
Time 時間形式
DateTime 日時形式
Pattern 正規表現


ルール設定をしたら、コントローラの中で使ってみましょう。該当するヘッダファイルをインクルードしておいてください。
フォームから取得したリクエストデータを検証します。検証エラーになった場合に、エラーメッセージを取得します。

QVariantMap blog = httpRequest().formItems("blog");
BlogValidator validator;
if (!validator.validate(blog)) {
    // 検証エラーになったルールのメッセージ取得
    QStringList errs = validator.errorMessages();
       :
}

通常、複数のルールを設定するはずなので、エラーメッセージも複数になります。1つ1つ処理するのは少々面倒なものです。
次のメソッドを使えば、検証エラーのメッセージを一括でエクスポートする(ビューに渡す)ことができます。第2引数には、エクスポートオブジェクトの変数名へのプレフィックスを指定します。

exportValidationErrors(valid, "err_");
結論: フォームのデータはルールを設定し、validate() で検証せよ。

カスタムバリデーション

上で説明した内容は静的なバリデーションの方法です。ある値に応じて、ある別の値の許容範囲が変わるような動的なケースでは使えません。この場合、validate() メソッドをオーバライドして、自由にバリデーションのコードを書くことができます。

次はサンプルコードです。

bool FooValidator::validate(const QVariantMap &hash)
{
    bool ret = THashValidator::validate(hash);  // ← 静的ルールのバリデーション
    if (ret) {
        QDate startDate = hash.value("startDate").toDate();
        QDate endDate = hash.value("endDate").toDate();
        if (endDate < startDate) {
            setValidationError("error");
            return false;
        }
          :
          :
    }
    return ret;
}

startDate の値と endData の値を比較して、正しくない場合に検証エラーにしています。