これまで,何とかのセットアップとかかんとか,環境整備の話題ばかりでSunvisorはちぃともコードを書いていないじゃないか。とだれかにしかられた訳ではありませんが,ちょっとコードがらみについても書いてみようと思います。話題はBAKE.PHPがはき出すコード(コントローラ編)です。だれもこんなところではつまずいたりしないとは思いますが,まぬけな僕はaddやeditのルーチンでひっかかりました。そこでBAKE.PHPが生成したコードを理解してみます。
indexとview
function index() { $this->Bookmark->recursive = 0; $this->set('bookmarks', $this->Bookmark->findAll()); }
ビューのbookmarksという変数に,Bookmarkモデルのすべてのレコードを渡しています。コントローラのメソッドでは,メソッドの最後で暗黙のうちにメソッドと同名のビューが表示されるとのことですので,その後index.thtmlビューが表示されます。このメソッドの場合は$bookmarksで渡されたデータをviewでどのように表示させるかという書き方の方が勉強になります。
function view($id = null) { if (!$id) { $this->Session->setFlash('Invalid id for Bookmark.'); $this->redirect('/bookmarks/index'); } $this->set('bookmark', $this->Bookmark->read(null, $id)); }
このメソッドでも,暗黙のビュー表示が呼び出されます。if文で括っているところは,idが指定されていなかったらエラーメッセージをセットしてindexを表示させるだけです。
addとedit
function add() { if (empty($this->data)) { $this->render(); } else { $this->cleanUpFields(); if ($this->Bookmark->save($this->data)) { $this->Session->setFlash('The Bookmark has been saved'); $this->redirect('/bookmarks/index'); } else { $this->Session->setFlash('Please correct errors below.'); } } }
function edit($id = null) { if (empty($this->data)) { if (!$id) { $this->Session->setFlash('Invalid id for Bookmark'); $this->redirect('/bookmarks/index'); } $this->data = $this->Bookmark->read(null, $id); } else { $this->cleanUpFields(); if ($this->Bookmark->save($this->data)) { $this->Session->setFlash('The Bookmark has been saved'); $this->redirect('/bookmarks/index'); } else { $this->Session->setFlash('Please correct errors below.'); } } }
この二つのメソッドの先頭にある
if (empty($this->data)) {
この条件分岐がはじめはよくわかりませんでした。これは,dataが空っぽの時にはということですよね。dataが空っぽってどういう状態?というのがよくわからなかったわけです。この二つのメソッドは2種類の呼び出され方をします。ひとつは,URLでメソッドが指定されて呼び出される場合。
http://localhost/cake/bookmarks/add
という風に入力された場合ということです。もう一つはビューのフォームがSubmitされた時にも同じメソッドが呼び出されるのです。URLで呼び出されるときにはdataはemptyなのでしょう(きっと,どういう理屈でそうなのかは今はわかりませんが)ですので先のif文が表すのは「もしもURLによって呼び出されたのなら」という意味なのでした。
すると,addの場合はURLで呼び出されたらビューを表示し,Submitで呼び出されたらビューから受け取ったデータをモデルに保存する処理をしているということがわかりました。editの方がちょっとコードが長いのは,既存のデータビューにセットしなければならないからですね。
このメソッドの書き方がCakePHPの普通な書き方なのでしょうか。bake.phpでこのコードが出てくるのだからそうなのでしょうね。僕としては少しわかりにくいように思います。それにデータ追加のビューを表示するメソッドと,実際にデータを追加するメソッドが同じものだという気持ち悪さを感じます。またelseブロックの中の処理はaddとeditでほとんど同じです。自分でコードを書くのならデータ追加のメソッドを分離して(例えばupdateとか),ビューのSubmit時にはそちらのメソッドを呼び出すようにしたいところです。
function add() { // 暗黙のビュー表示 }
function edit($id = null) { if (!$id) { $this->Session->setFlash('Invalid id for Bookmark'); $this->redirect('/bookmarks/index'); } $this->data = $this->Bookmark->read(null, $id); }
function update() { $this->cleanUpFields(); if ($this->Bookmark->save($this->data)) { $this->Session->setFlash('The Bookmark has been saved'); $this->redirect('/bookmarks/index'); } else { $this->Session->setFlash('Please correct errors below.'); $this->redirect(???); // 元のビューを表示する(やり方は不明) } } }updateメソッドにはどのビューから呼び出されたのかを知る方法が必要ですね。これはあとで調査します。CakePHPガイドブックのログイン画面の例でも,loginメソッドとlogin_cmpメソッドが用意され,loginビューからはlogin_cmpが呼び出されるようになっています。この方がすっきりすると思うのですが,いかがでしょうか。