こんにちは、株式会社アリアです。

FuelPHP を利用して開発を行っていた案件にて、以下の問題が発生しました。

Web ブラウザ上でユーザーが入力した項目に対する入力チェック(バリデーション)処理を、FuelPHP に実装した独自バリデーションで行ったところ、同一バリデーションルールが適用された複数の項目でエラーが発生した場合に、最後にチェックされた項目のエラーメッセージのみとなってしまいました。

その際のコードは、FuelPHP で一般的なバリデーション設定の書き方をしていました。

$val = Validation::forge();
$val->add_callable('MyRules');
// _validation_originalRule メソッドが独自バリデーションにあります
$val->add('field_1', '項目1')->add_rule('originalRule');
$val->add('field_2', '項目2')->add_rule('originalRule');

項目1,2 いずれもエラーとなった場合の期待値は以下ですが、

・項目1 は originalRule に従っていません
・項目2 は originalRule に従っていません

実際には以下のようになってしまう、という問題です。

・項目2 は originalRule に従っていません
・項目2 は originalRule に従っていません

FuelPHP の core ソースを調べてみたところ、一つのバリデーションルールには一つのメッセージしか保持できない、という仕様になっているためだと分かりました。

しかし、何らかの手があるはずです。

そう思いながら Google 先生に尋ねてみたのですが、ビンゴな回答が見つかりません。

そこで、再び FuelPHP の core ソースを眺めつつ試行錯誤したところ望む結果を得ることが出来ました。

$val = Validation::forge();
$val->add_callable('MyRules');
$val->add('field_1', '項目1')->add_rule(['field_1_originalRule' => array('MyRules', '_validation_originalRule')], 'field_1_originalRule');
$val->add('field_2', '項目2')->add_rule(['field_2_originalRule' => array('MyRules', '_validation_originalRule')], 'field_2_originalRule');

add_rule の第一引数が配列となっているのが最大のポイントで、適用したいルール(MyRules クラスにある _validation_originalRule メソッド)に別名を付ける、という事をしています。

これにより、「field_1 には field_1_originalRule という名称のルール」「field_2 には field_2_originalRule という名称のルール」が適用され、適用されるルールの実体は「MyRules クラスにある _validation_originalRule メソッド」となります。

add_rule の第二引数は、ルールの別名と一緒としているのもポイントで、MyRules クラスに実装したバリデーションメソッドは以下のようになっています。

_validation_originalRule($val, $name) {
    // バリデーションエラー時に以下をセット
    Validation::active()->set_message($name, ':label は originalRule に従っていません');
}

これにより、項目1,2 いずれもエラーとなった場合の期待値どおりとなりました。

・項目1 は originalRule に従っていません
・項目2 は originalRule に従っていません

この記事が、FuelPHP を利用した開発の役に立てば幸いです。