cakePHP+smartyでキャッシュを効かせる
cakePHPでSmartyを使用しているとキャッシュに苦労します。
cakePHP標準のキャッシュが使えるtipsを見つけたいものですが、、、
今回はsmartyのキャッシュを使う方法ですが、落とし穴があるかも知れませんので自己責任でお願いします。
cakeははじめにいろいろ自分の初期化をしてデータベースアクセスし、最後にVIEWを生成します。
このうち初期化の後にキャッシュチェックをして有効であれば、その後をスルーすることにします。
smartyは独自にキャッシュメカニズムを持っているのですが、最後にならないとsmartyが働かないので、コアに手を入れて初期化直後にVIEWクラスを生成します。
まず、smarty内部でキャッシュファイルを生成するようにします。
(私はrequestActionでブロック表示しているものだけキャッシュしたかったので、bareを見ています)
/app/views/smarty.phpの「function __construct」関数($this->ext= '.tpl';とか設定しているところ)の最後に、
if($this->params['bare'] == '1') {
$this->Smarty->cache_lifetime = 3600; //有効秒数
$this->Smarty->caching = true; //有効化
$this->cacheid = $this->params['url']['url']; //url毎にキャッシュファイルを生成する。テンプレート単位でキャッシュする場合は不要
}
function _render(...)の最後のfetchを以下に変更、
return $this->Smarty->fetch($___viewFn, $this->cacheid);
/cake/dispatcher.phpの 240行目あたり(return $this->_invoke(...)の直前)で、
include_once(VIEWS."smarty.php");
$viewClass =& new SmartyView($controller);
$tplfile = $viewClass->_getViewFileName($this->params['action']);
if($viewClass->Smarty->is_cached($tplfile,$this->params['url']['url']) === true) {
$viewClass->render();
return;
}
smarty.phpをインクルードしてVIEWクラスを生成し、is_cached関数が真の場合、renderしてreturnしてしまいます。
ちなみにsmartyテンプレートからcakeのrequestActionを呼ぶにはヘルパーを自作しました。
/app/views/helpers/block.php
<?php
class BlockHelper extends AppHelper {
//requestAction
function fetch($address = null) {
$this->pageTitle = $title;
if(!$address) return;
$output = $this->requestAction($address, array('return'));
return $this->output($output);
}
}
?>
コントローラーにhelpers宣言しておいて、テンプレートからは
{$block->fetch("/tags/index")}
でNucleusライクに他のアクションの描画結果を呼び出せます。
もっと追加^^)smartyでfetchした結果を再度render評価します。
ブログや管理画面で本文を入力した内容にsmarty関数を書いたりした場合に、一度fetchして再度fetchすることによって巻数を展開します。
smartyにはリソースプラグインという機能があり、ファイルとしてテンプレートを読み込む以外にデータベースなどからテンプレートを読み込めるわけですが、なぜかPHP変数をテンプレートとして使えません。smartyプラグインとして作成します。ここではファイル名は「resource.memory.php」
<?php
function smarty_resource_memory_source($tpl_name,&$tpl_source,&$smarty_obj){
$tpl_source = $tpl_name;
return true;
}
function smarty_resource_memory_timestamp($tpl_name,&$tpl_timestamp,&$smarty_obj){
$tpl_timestamp = time();
return true;
}
function smarty_resource_memory_secure($tpl_name,&$smarty_obj){
return true;
}
function smarty_resource_memory_trusted($tpl_name,&$smarty_obj){
}
?>
/cake/dispatcher.phpの上記fetch箇所を
$text = $this->Smarty->fetch($___viewFn, $this->cacheid);
if(strpos($text, $this->Smarty->left_delimiter) !== false) {
$text = $this->Smarty->fetch("memory:".$text);
}
return $text;

