Themeを使えばRoutingPrefixを使う振り分けの時よりControllerがシンプルになる

書こうと思いましたが既に書かれてました。そりゃそうですね。
cakephp1.3携帯サイトをテーマを使って作る
http://www.hideblog.net/nikkis/show/125/
同じことがCakePHP2.xでも変わらず実装できるよということで一応書いておきます。

themeは1系からある機能でしたが、今までずっとprefixを信じてここまでやってきたので全然触れたことがありませんでした。
今回、少し規模というかactionの多いサイトを作っていて、あまりにmethodが多くなったのでthemeを使うことにしてみました。

themeを使ってビューの振り分けを実装すると、今までprefixで指定してた時は

<?php
class ExampleController extends AppController {
	//PC用
	public function index() {
	}
	//携帯用
	public function mobile_index() {
	}
	//スマフォ用
	public function sp_index() {
	}
}
?>

のようにメソッドが増えたわけです。
こういう時って大抵、画面に引っ張るデータは同じで、ビューだけ変えたいってことが多いので、
全部のメソッドに同じような処理を書くか、共通メソッドを作って呼び出す形になると思います。
これは面倒です。

themeを使うと、prefixがつかなくなるので

<?php
class ExampleController extends AppController {
	public function index() {
	}
}
?>

これだけで済みます。シンプルイズベスト!

自分の場合はシングルトンなUserAgent判別クラスを作り、使用するtheme名を先に決めています。

<?php
// Vendor/UA.php
	public function __construct() {
		$this->theme = $this->getThemeName();
	}
	public function getThemeName() {
		if ($this->isSmartphone()) {
			$result = 'sp';
		} elseif ($this->isMobile()) {
			$result = 'mobile';
		} else {
			$result = 'pc';
		}
		return $result;
	}
?>

その後、AppControllerのbeforeFilter()で$this->themeにtheme名をセットしています。

<?php
// app/Controller/AppController.php
	public function beforeFilter() {
		parent::beforeFilter();
		$this->UA = UA::getInstance();
		$this->theme = $this->UA->theme;
	}
?>

controllerのthemeに名前が入っていると、cakeは読み込むviewファイルの位置を
app/View/Themed/[theme]
以下から探すようになります。
(Themedの中に無かった場合は本来の階層からファイルを探してくれます。)

これで、themeが'mobile'の場合は
app/View/Themed/mobile/example/index.ctp
themeが'sp'の場合は
app/View/Themed/sp/example/index.ctp
を読み込んでくれるようになります。

LayoutやElementもmobile_menu.ctpとかmobile_layout.ctpみたいな名前付けて区別してましたが、
themeを使うとThemed/[theme]/(Layouts|Elements)/の下にあるものを呼んでくれるので、ファイル名もシンプルになります。


themeを使った実装は、ユーザーのブラウザ環境が違ってもURLが同じになります。
PCでアクセスしようがガラケーだろうがスマフォだろうが
http://example.com/example/index
でアクセスできます。


prefixを気にしなくて良いので、app/Config/routes.phpもシンプルになりました。スンバラシ。