例えば選択されたラジオボタンによって必須項目が変わるような、あるモデルのファイル内で、複数パターンのバリデーションチェックをしたいと思い、昨日、新幹線の中で悶々としてました。
とりあえず下記のように対応してみた。
cakePHPのバージョンは、1.2RC1です。
モデルファイル
<?php class Order extends AppModel { var $name = 'Order'; var $validate = array( 'username' => array( "rule1" => array('rule' => VALID_NOT_EMPTY, 'required' => true, 'message' => 'ユーザ名を入力してください' ), ), ); var $validate2 = array( 'companyname' => array( "rule1" => array('rule' => VALID_NOT_EMPTY, 'required' => true, 'message' => '会社名を入力してください' ), ), ); } ?>
上記のように、通常は$validateの方のバリデーションがコントローラから実行されます。
ラジオボタンで、例えば個人と法人を選択するようにしておいて、個人の場合は名前だけのチェック、法人の場合は会社名と名前の両方をチェックするという場合に、
法人の場合は$validateの後に、$validate2の方のバリデーションを実行するため、コントローラ側では下記のようにしました。
//バリデーションチェック(名前のチェックのみ) $this->Order->set($this->data); $error = $this->validateErrors($this->Order); //法人の場合のチェック if($this->data['Order']['companyflag'] == 1){ $this->Order->validate = $this->Order->validate2; $error2 = $this->validateErrors($this->Order); if(!empty($error2)){ if(!empty($error)){ $error = array_merge($error, $error2); }else{ $error = $error2; } } } //バリデーションエラーがあれば、index画面に戻し、エラーを表示する if(!empty($error)){ //バリデーションがエラーになったら、indexのhtmlを読み込む $this->set("errors",$error); $this->setAction("index"); }
Viewでは、コントローラから渡される$errorの配列の内容をforeachでまわしてエラーを出力します。
<?php if(!empty($errors)){ echo "<font color=red>"; foreach ($errors as $error){ echo h($error) . "<br/>"; } echo "</font>"; } ?>
今回の方法は、コントローラで実行するバリデーションメソッド$this->validateErrorsが、モデル内の$validate変数を参照するという仕様で、$validate変数以外は参照しないという点から、
$this->Order->validate = $this->Order->validate2;
として、$validate変数に、$validate2の変数の内容を入れてしまうという方法で対応しました。
追記
もう少しスマートな方法が載ってた。
http://bakery.cakephp.org/articles/view/multivalidatablebehavior-using-many-validation-rulesets-per-model