add to hatena hatena.comment (7) add to del.icio.us (0) add to livedoor.clip (1) add to Yahoo!Bookmark (0) Total: 8

CakePHP Behaviorでバリデーション周りの効率化を図る 応用編

前回紹介したBasicValidationBehaviorを使って、動的にバリデーションを切り替える方法を紹介します。
共通のモデルを複数のフォームで利用している場合にバリデーションの定義を動的に変更したい場合などに有効です。

例1:新規登録時と編集時でバリデーションの登録項目を変更する

対応1)loadValidate()メソッドに引数を追加し、条件によって分岐させる

[モデル内の処理]

PHP:
  1. function loadValidate($action = 'add') {
  2.     $valid = array(
  3.         'name'   => 'required | maxLen[50]',
  4.         'email'         => 'required | email | isUnique | maxLen[200]',
  5.         'password'  => 'required | single | maxLen[20] | minLen[6]',
  6.         're_password'   => 'required | confirm[password]',
  7.         'sex'     => 'required | numeric | maxLen[1]',
  8.         'birthday'  => 'required | ymd',
  9.         'tel'      => 'required | phone | maxLen[13]',
  10.         'zip'      => 'required | zip | maxLen[8]',
  11.         'pref'    => 'required | maxLen[12]',
  12.         'addr1'      => 'required | maxLen[200]',
  13.         'addr2'      => 'maxLen[200]',
  14.     );
  15.     // 新規登録時以外はパスワード関連の項目を無効にする
  16.     if($action !== 'add'){
  17.         unset($valid['password']);
  18.         unset($valid['re_password']);
  19.     }
  20.     $this->setValidate($valid);
  21. }

対応2)コントローラーでモデルのvalidate()やsave()前にloadValidate()を明示的に実行する

[コントローラー内の処理]

PHP:
  1. function add(){
  2. // 処理を省略
  3.  
  4.     $this->TestUser->set($this->data);
  5.     // バリデーションを設定
  6.     $this->TestUser->loadValidate('add');
  7.     if($this->TestUser->validates()) {
  8.    
  9. // 処理を省略
  10. }
  11.  
  12. function edit($id = null){
  13. // 処理を省略
  14.  
  15.     $this->TestUser->id = $id;
  16.     $this->TestUser->set($this->data);
  17.     // バリデーションを設定
  18.     $this->TestUser->loadValidate('edit');
  19.     if($this->TestUser->validates()) {
  20.    
  21. // 処理を省略
  22. }

例2:入力された条件でバリデーションを変更したい

例として、性別が女性(sex==2)だったら電話番号(tel)を必須にする場合

対応)loadValidate()メソッド内で$this->data(モデルのデータ)により分岐させる

[モデル内の処理]

PHP:
  1. function loadValidate() {
  2.     $valid = array(
  3.         'name'   => 'required | maxLen[50]',
  4.         'email'         => 'required | email | isUnique | maxLen[200]',
  5.         'password'  => 'required | single | maxLen[20] | minLen[6]',
  6.         're_password'   => 'required | confirm[password]',
  7.         'sex'     => 'required | numeric | maxLen[1]',
  8.         'birthday'  => 'required | ymd',
  9.         'zip'      => 'required | zip | maxLen[8]',
  10.         'pref'    => 'required | maxLen[12]',
  11.         'addr1'      => 'required | maxLen[200]',
  12.         'addr2'      => 'maxLen[200]',
  13.     );
  14.     // 性別が女性(sex==2)だったら電話番号(tel)を必須
  15.     if(isset($this->data['TestUser']) && isset($this->data['TestUser']['sex']) && $this->data['TestUser']['sex'] == 2){
  16.         $valid['tel'] = 'required | phone | maxLen[13]';
  17.     }else{
  18.         $valid['tel'] = 'phone | maxLen[13]';
  19.     }
  20.     $this->setValidate($valid);
  21. }

※上記の例ではmodel->set()によりデータが設定された後にmodel->validate()が実行されることを想定しています。
※明示的に行う場合は、以下のようにmodel->set()後にmodel->loadValidate()を明示的に実行します。
[コントローラー内の処理]

PHP:
  1. function edit($id = null){
  2. // 処理を省略
  3.  
  4.         $this->TestUser->id = $id;
  5.         $this->TestUser->set($this->data);
  6.         // データセット後にバリデーションを変更する
  7.         $this->TestUser->loadValidate();
  8.         // 以下はいつもの処理
  9.         if($this->TestUser->validates()) {
  10.             $M->save();
  11.             $this->Session->setFlash('情報を保存しました。');
  12.             $this->redirect(array('action'=>'edit'.DS.$id));
  13.             return;
  14.         } else {
  15.             $this->Session->setFlash('入力に誤りがあります。内容を確認してください。');
  16.         }
  17.         $this->data = am($this->data, $this->TestUser->data);
  18.        
  19. // 処理を省略
  20. }

例3:POSTされたデータのみチェックしたい

管理画面などで一部の項目だけを更新するフォームが数パターンあることを想定。
例1のような分岐処理でも対応できますが、ビヘイビアのintersectValidate()メソッドを利用するほうが簡単です。

対応)コントローラーでモデルのvalidate()やsave()前にintersectValidate()を実行する

[コントローラー内の処理]

PHP:
  1. function edit($id = null){
  2. // 処理を省略
  3.  
  4.         $this->TestUser->id = $id;
  5.         $this->TestUser->set($this->data);
  6.         // POST されたものだけをチェックする
  7.         $this->TestUser->intersectValidate($this->data);
  8.         // 以下はいつもの処理
  9.         if($this->TestUser->validates()) {
  10.             $M->save();
  11.             $this->Session->setFlash('情報を保存しました。');
  12.             $this->redirect(array('action'=>'edit'.DS.$id));
  13.             return;
  14.         } else {
  15.             $this->Session->setFlash('入力に誤りがあります。内容を確認してください。');
  16.         }
  17.         $this->data = am($this->data, $this->TestUser->data);
  18.        
  19. // 処理を省略
  20. }

例4:特定の項目のみチェックしたい

対応)例2のようにintersectValidate()メソッドを使い、引数に項目名配列を渡します

[コントローラー内の処理]

PHP:
  1. function edit($id = null){
  2. // 処理を省略
  3.  
  4.         $this->TestUser->id = $id;
  5.         $this->TestUser->set($this->data);
  6.         // 特定の項目だけをチェックする
  7.         $this->TestUser->intersectValidate(array('name', 'email'));
  8.         // 以下はいつもの処理
  9.         if($this->TestUser->validates()) {
  10.             $M->save();
  11.             $this->Session->setFlash('情報を保存しました。');
  12.             $this->redirect(array('action'=>'edit'.DS.$id));
  13.             return;
  14.         } else {
  15.             $this->Session->setFlash('入力に誤りがあります。内容を確認してください。');
  16.         }
  17.         $this->data = am($this->data, $this->TestUser->data);
  18.        
  19. // 処理を省略
  20. }

関連するその他の記事

Comments

Leave a Reply