バリデーション
リクエストとして送られてくるデータは、開発者が望んだ形式で送られてこないかもしれません。数値を入力すべきフィールドにアルファベットを入力するユーザがいるかもしれません。たとえクライアントサイドの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 の値を比較して、正しくない場合に検証エラーにしています。



