CakePHP2でリダイレクト先にバリデーションメッセージを表示する
Tutoriel CakePHP : Validate & Redirect - YouTube
登録画面やログイン画面なんかは、たいていアクションとビューが一致しているので特に気にしなくてもバリデーションエラーの時に、Cake側がメッセージ等々を表示してくれます。
ところが、たとえば記事に対するコメントや、一覧画面に追加フォームを設置したいこともあります。その場合、たいていはバリデーションエラーでsaveができないと、元の画面にリダイレクトしたかったりします。そうするとsetFlashしたメッセージは表示できてもバリデーションエラーはリダイレクト時に破棄されるためフォームが書いてあるビューには表示されません。
上の動画では、そういった場合の対応方法が解説されています。
具体的には、バリデーションのエラーがあった場合にセッションに書き込んでそれをコントローラ側で読み取ってコントローラの持ってるModel::validationErrors
に渡せば良いだけだった。
例えば、ユーザのトップ画面で(別のモデルの)ブックマークを保存したいとします。 ブックマークのURLを下のようにバリデートするとします。
<?php class Bookmark extends AppModel{ public $validate = [ 'url' => [ 'rule' => ['url',true], 'message' => 'Invalid url' ] ]; } ?>
まず、実際に保存するモデルに紐付いたコントローラで失敗時にバリデーションエラーをセッションに書き込みます。
<?php class BookmarksController extends AppController{ public function add(){ if( $this->Bookmark->save($this->request->data) ){ $this->Session->setFlash(__('The bookmark has been saved.')); } else { //バリデーションやSQLエラーで保存できない場合 $this->Session->write('errors.Comment',$this->Bookmark->validationErrors); $this->Session->setFlash(__('Failed to save.')); } } $this->redirect( $this->referer() ); // 今回のキモ。自前でrenderしないでどこかにリダイレクトする } ?>
次に、ビューに紐付いたコントローラ側でセッション情報を読み取らせます。AppModel::beforeFilter()
に書いてしまったほうが楽です。(ビデオではそうしています)
<?php class UsersController extends AppController{ var $components = ['Session']; public function beforeFilter(){ if($this->Session->read('errors')){ foreach($this->Session->read('errors') as $model => $errors){ $this->loadModel($model); $this->$model->validationErrors = $errors; } $this->Session->delete('errors'); //表示は遷移・リロードまでの1回っきりなので消す } } } ?>
こうすることで、リダイレクト先のフォームにもバリデーションの結果が表示されるようになります。 (FormHelper以外でフォームを出している場合は、バリデーションエラーをちゃんと表示するようなロジックも必要になりますが)
そういえば、読書記録以外にはじめて書きました。