cakephpのルーティングとprefix

 cakephpで一般ユーザー画面と管理画面を分けたいとき,Routing.prefixes を使うと便利である。例えば /:controller/:action を一般ユーザー画面,/admin/:controller/:action/ を管理画面にしたい場合は app/config/core.php に次のように設定する。

	Configure::write('Routing.prefixes', array('admin'));

これで URL が /admin/hoge/fuga/ だと HogeController.php 内の admin_fuga() 関数で管理画面用のアクションを設定できる。また,コントローラ内で $this->params[‘prefix’] とすると ‘admin’ が取得できる。

問題発生

 便利だなーと思っていたが,ここで問題が発生。URLでコントローラ名などを省略すると $this->params[‘prefix’] が取得できない。 コントローラ名の省略による挙動は app/config/routes.php が制御していて,デフォルトだと下記のようになっている。

	Router::connect(
		'/', 
		array(
			'controller' => 'pages', 
			'action' => 'display', 
			'home'
		)
	);
	Router::connect(
		'/pages/*', 
		array(
			'controller' => 'pages', 
			'action' => 'display'
		)
	);

この記述によって,コントローラ,アクションを省略し,URLを / とすると,コントローラに pages, アクションに display が割り当てられる。

さて,ここで prefixを admin にし,コントローラ,アクションを省略すると URL は /admin/ だが,こう書いてしまうと コントローラが 「admin」だと勘違いしてしまい,AdminController.php を参照しようとしてしまう。そこで以下の記述を追加してみた。

	Router::connect(
		'/admin/', 
		array(
			'controller' => 'pages', 
			'action' => 'display'
		)
	);

こうするとpages コントローラ,display アクション を取得できた。ところが先ほど挙げた $this->params[‘prefix’] が null になってしまうし,関数も admin_display() ではなく display() を参照してしまう。

解決

app/config/routes.php 以下の記述を追加すると思い通りの動作をするようになった。

	Router::connect(
		'/admin/', 
		array(
			'controller' => 'pages', 
			'action' => 'display',
			'admin' => true
		)
	);