CakePHPでサイトを作るのに気をつかったところ
PookはCakePHPで作っています。
Pookに限らずCakePHPでサイトを作るのに個人的に気を使うところを書いてみます。
CakePHPのバージョンは1.3.6前提です。
RequestHandlerコンポーネントを使いこなす
Pookはページネーションは全てajaxで取得するようにしています。そのためページネーションされる可能性があるところはすべてjson出力されるようになっています。例えばユーザーページの場合、どちらもアクセスできます。
http://pook.jp/taizo http://pook.jp/taizo.json
これは、RequestHandlerコンポーネントで.jsonの場合と、デフォルト(.html)の場合でviewファイルを分けています。ざっくりやり方を書くと
1. config/routes.php に Router::parseExtensions()を追加
Router::parseExtensions('json');
2. APP/views/layouts/json/default.ctp を設置する
<?php header('Content-type: application/json'); echo $content_for_layout; ?>
3. jsonの出力が必要な箇所にviewファイルを用意する
views/articles |-- index.ctp // html `-- json `-- index.ctp // json
Paginationの取り扱い
上の項目でajax使っていると書きましたが、PookではAjaxヘルパーは使っていません。
CakePHPで使うPaginatorヘルパーを使ってリンクを出力し、それをjavascriptでイベントを追加するようにしています。
なので2ページ目から、直接見たい場合のリンクもきちんとhtmlで動くようにしています。
http://pook.jp/taizo/index/page:2 (2ページ目からクォートが表示されます)
routes.php のテストは必ず書く
APP/config/routes.php を複雑にしていくと、Paginatorヘルパーのリンク生成と整合性が取れなくなるときがあります。
なので、routes.phpを少しでもいじる場合はテストを書いたほうが良いです。
CakePHPの中でも、routes.php のテストは最も簡単な部類です。
CakePHP式のテストの書き方に慣れるには、ここから入るのがオススメです。
view内の再利用
複数のページに共通のUI(ブログの場合、サブカラムのメニューなど)があって、それを再利用したい場合、いくつか方法があります。適時使い分けることになります。
Skinny Controller, Fat Model
Skinny Controller, Fat Modelなんていうコントローラを薄くして、モデルは厚くしろなんていう言葉がありますが
CakePHPでもコントローラは薄いほうが良いかと個人的に思います。
理由は1つで、テストが書きづらいからです。僕の中で、CakePHPでテストの書きやすさを並べるとこんな感じになります。
- Models
- Behaviors
- Components
- Controllers
- Views
コントローラのテストが書きづらい理由
例えば、ブログで最新の自分の記事10件を取ってくることになった場合
<?php class ArticlesController extends AppController { var $components = array( 'Auth', ); var $paginate = array( 'limit' => 10, 'order' => 'created desc', ); function index() { $this->set('result', $this->paginate('Article', array('user_id' => $this->Auth->user('id')))); } }
テストを走らせる時に、ログイン状態を保持するようにしなければいけないです。
Securityコンポーネントを使った場合
<?php class ArticlesController extends AppController { var $components = array( 'Security', ); function beforeFilter() { $this->Security->requirePost('add'); parent::beforeFilter(); } function add() { // 記事の追加 } }
この場合も、POSTで無くてはaddコントローラを呼び出せないため、RequestHandlerComponent::isPost() をtrueで返すようにテストケース側に仕込む必要があります。
解決するためには、やはりモデルや、コンポーネントなどに処理を移動させます。
あと、ビューのテストはSeleniumなどを使ったほうが僕は好きです。
まとめ
CakePHPを使いはじめて1年半くらい経ったので
来年こそ、やる気を出してブログにネタを書いてみようかなと思います。
*1:大抵はキャッシュの問題があるので、headerにCache-Controlなどを設定することになります。