CakePHPアプリケーションの基本的な設計指針 (1) - URL設計 -
イントロダクション
CakePHPはMVCデザインパターンを採用しており、基本的にこれに従った設計が基本となります。
しかし、ある程度開発が進んだところで、やっかいな設計の問題にぶち当たることは多いですよね。
そこで、よくある問題を取り上げて、設計の指針としてまとめてみることにします。
注:とても1回で書ききれるとは思えません。連載となる可能性が高いです。
URL設計
CakePHPのURLは、最初は独特に見えたかもしれません。
http://example.com/users/view/1 などよりも、http://example.com/user/hiromi2424 などの見栄えを期待していた方も多いのではないでしょうか。
しかし、だからといって以下のようなアクション、URLの呼び出し方は、後々に響いてきます。
<?php // Route Router::connect( '/user/:nickname', array( 'controller' => 'users', 'action' => 'view' ), array( 'pass' => array('nickname'), ) ); ?> <? // Controller class UsersController extends AppController{ function view($nickname) { $this->set('user', $this->User->findByNickname($nickname)); } } ?> <?php // View echo $this->Html->link($user['User']['nickname'], '/user/' . $user['User']['nickname']); ?>
大きく3点の問題があります。
- URLを呼び出す時に、User.nicknameが必要(user_idしかなかったらどうする?)
- ニックネームの重複が許されない
- ルートが変更された場合、ビュー、コントローラなどの該当URL呼び出しを全て変更する必要がある
IDをURLに含めるかは要件次第ですが、たったこれだけのことで後に重大な変更になりかねません。
URLにIDが含まれていなくても、IDを元にアクションの引数、URLを扱うように設計していればその心配がなくなります。
また、CakePHP1.3からは、カスタムルートクラスが利用できます。
これを利用することにより、標準的なアクションの形で様々なURLを利用することが可能となります。
<?php // Route App::import('Lib', 'route' . DS . 'UserNicknameRoute'); Router::connect( '/user/:id/:nickname', array( 'controller' => 'users', 'action' => 'view' ), array( 'routeClass' => 'UserNicknameRoute', 'pass' => array('id'), ) ); ?> <?php //RouteClass class UserNicknameRoute extends CakeRoute { function match($params) { // controller, actionの比較 if (array_intersect_key($params, $this->defaults) != $this->defaults) { return false; } if (isset($params[0])) { // 実際はキャッシュするべき $params['id'] = $params[0]; $params['nickname'] = rawurlencode(ClassRegistry::init('User')->field('nickname', array('id' => $params[0]))); unset($params[0]); } return parent::match($params); } } ?>
URLがニックネームが違っていてもマッチしてしまう場合は、カスタムルートクラスのparse()を実装するか、コントローラ(コンポーネント)でチェックなどをして工夫しましょう。
また、文字列でのURLの呼び出し('/user/' . $user['User']['nickname'])は極力しないようにしましょう。
ただし、例外はあります。
- ホームページ('/'を指定)
- 画像などアセットのパス
- 外部URL
など。
呼び出すURLがアクションの場合、必ず標準的な配列形式で指定するようにしましょう。
最後に
これらCakePHPの機能に配慮した設計を行うことにより、変更に強く、また柔軟なルーティングが行えます。
億劫な配列地獄に見えるかもしれませんが、そこにはちゃんと規約のマジックが存在するのです。
#URL設計だけで1回終わってしまった・・・どうなることやら。