※ 5月16日 テーマ別のキャッシュ方法を追記!
携帯サイトの場合はキャリア別に絵文字振り分けするのでキャッシュを取らない方が良い。
まず、ビューキャッシュとは動的ページを静的ページとして吐き出すことだ。
だから、びっくりするくらい軽くなる。
サーバーを高級なプランにするより、キャッシュを取った方が安くて、早い。
下準備
キャッシュを有効にし、
debug が 0の本番モードの時のみキャッシュを行い、それ以外はキャッシュさせない。
core.php
以下の項目をそれぞれコメントアウト
//Configure::write('Cache.disable',true);
//Configure::write('Cache.check', false);
で、以下の項目を追加。
if(Configure::read('debug') > 0){
Configure::write('Cache.disable',true);
Configure::write('Cache.check', false);
} else {
Configure::write('Cache.disable',false);
Configure::write('Cache.check', true);
}
使いたいコントローラーで アクション名 => キャッシュしたい秒数 で指定。
hoges_contoroller.php
var $cacheAction = array(
'lotlist' => 7200,
'lot' => 7200
);
ユーザー名などのSESSIONデータはキャッシュさせない
基本的に全てキャッシュしてしまうのでそのまま使うとユーザー名が全て同じ人で
ログインしたことになってしまう。
なのでユーザー名はキャッシュしないようにする。
<?php echo $today;?> <cake:nocache> ごはん <?php echo $_SESSION['Auth']['User']['name'] ;?> </cake:nocache>
とすれば
10月25日 <cake:nocache> ごはん <?php echo $_SESSION['Auth']['User']['name'] ;?> </cake:nocache>
と、 nocache 以外のところが処理され、nocache としたところは 変数がそのまま残る。
そもそもcakephpキャッシュというのは
キャッシュ未使用
モデル → コントローラー → ビュー
キャッシュ使用
ビュー
という処理の流れにするので、$_SESSION以外のコントローラーから受け渡されるはずの $today を
nocache にしてしまうと $today がないよと怒られてしまう。
リアルタイムランキングなどで $today もどうしても使いたい場合は そのコントローラーの処理も
、nocacheタグ内に含めて書こう。
まとめると
nocaheはキャッシュしないのではなく、phpの処理をそのままphpの処理として保存する
またキャッシュデータは
/app/tmp/cahche/views/
に格納される。
キャッシュを削除する場合は、このキャッシュファイルを直接削除すればいい。
theme別のキャッシュ
これは迷った。やり方が載ってない。
一度あきらめたけど、結局探り続けてできるようになった。
だって、外国のcakephpサイトは
view cache やめて、element cache にしやーよ。としか書いてないし。泣
キャッシュはコントローラーやモデルの処理を一切シカトする。
よってキャッシュを書き込む際は
app_controller.php の beforeRender や beforeFilter が有効になるが、
キャッシュを読み込む際は 上記処理をシカトするので別場所に携帯かどうかを判別する処理を書く必要がある。
携帯からのアクセスかを判定
function beforeRender()
{
//iphone or android の場合。
if($this->Ktai->is_iphone() || $this->Ktai->is_android()){
//携帯からのアクセスの場合はキャッシュさせない(デバッグ時に便利。)
//Configure::write('Cache.disable',true);
//Configure::write('Cache.check', false);//false なら キャッシュチェックしない
$this->view = "Theme";
$this->theme = "s";
}
}
//2011/11/11追記
スマートフォンサイトを作って、PCサイトはこちらからリンクを作りたいときがある。
そんなときはこうする。
defaultsコントローラー
function change()
{
$res = $this->Cookie->read('view');
if($res){
$this->Cookie->delete('view');
} else {
$this->Cookie->write('view','pc');
}
$this->redirect('/');
$this->autoRender = false;
}
change にアクセスしたら viewクッキーに pc と書き込む。
逆に、 viewクッキーにpcがセットされていたら削除。
要は、PC用の表示じゃなけりゃスマふぉ用のキャッシュを作れよと。
app_controller beforefilter
if($this->Cookie->read('view') != 'pc'){
$this->view = "Theme";
$this->theme = "s";
}
app_controller beforeRender
if($this->Cookie->read('view') == 'pc'){
$this->view = "Theme";
$this->theme = "s";
}
if($this->here == '/'){
$this->layout = 'top';
} else {
$this->layout = 'default';
}
次は読み込み。ここではまった。
/cake/dispatcher.php
if($this->Ktai->is_iphone() || $this->Ktai->is_android() || Configure::read('sphoneTest')){
if(!isset($_COOKIE['CakeCookie']['view'])){
$path = 's_'.$path;
}
}
スマートフォン用の view がセットされていなけりゃスマふぉ用のキャッシュを使えよ。
でも、セットされてたらPC用を表示したいので何もすんなよってこと。
//キャッシュを読み込む処理
変更点: テーマがあればテーマ用のファイル名で保存
/cake/dispatcher.php
cached 520行目
function cached($url) {
if (Configure::read('Cache.check') === true) {
$path = $this->here;
if ($this->here == '/') {
$path = 'home';
}
//テーマ別にキャッシュを分ける
App::import('Vendor', 'ecw' , array('file' => 'lib3gk.php'));
$this->Ktai = new lib3gk();
if($this->Ktai->is_iphone() || $this->Ktai->is_android() || Configure::read('mobileTest')){
$path = 's_'.$path;//return false; にすればキャッシュを作らない。
}
$path = strtolower(Inflector::slug($path));
$filename = CACHE . 'views' . DS . $path . '.php';
if (!file_exists($filename)) {
$filename = CACHE . 'views' . DS . $path . '_index.php';
}
if (file_exists($filename)) {
if (!class_exists('View')) {
App::import('View', 'View', false);
}
$controller = null;
$view =& new View($controller);
$return = $view->renderCache($filename, getMicrotime());
if (!$return) {
ClassRegistry::removeObject('view');
}
return $return;
}
}
return false;
}
/app/views/helpers/cache.php 196行目
変更点: このメソッドはキャッシュがあろうがなかろうがおこなれるので、ここでKtailibraryを読み出し、
携帯からのアクセスかどうかを判断する。
_writeFile
function __writeFile($content, $timestamp, $useCallbacks = false) {
$now = time();
if (is_numeric($timestamp)) {
$cacheTime = $now + $timestamp;
} else {
$cacheTime = strtotime($timestamp, $now);
}
$path = $this->here;
if ($this->here == '/') {
$path = 'home';
}
//テーマ別にキャッシュを分ける
$path = $this->theme.'_'.$path;
$cache = strtolower(Inflector::slug($path));
if (empty($cache)) {
return;
}
$cache = $cache . '.php';
$file = '<!--cachetime:' . $cacheTime . '--><?php';
if (empty($this->plugin)) {
$file .= '
App::import(\'Controller\', \'' . $this->controllerName. '\');
';
} else {
$file .= '
App::import(\'Controller\', \'' . $this->plugin . '.' . $this->controllerName. '\');
';
}
$file .= '$controller =& new ' . $this->controllerName . 'Controller();
$controller->plugin = $this->plugin = \''.$this->plugin.'\';
$controller->helpers = $this->helpers = unserialize(\'' . serialize($this->helpers) . '\');
$controller->base = $this->base = \'' . $this->base . '\';
$controller->layout = $this->layout = \'' . $this->layout. '\';
$controller->webroot = $this->webroot = \'' . $this->webroot . '\';
$controller->here = $this->here = \'' . $this->here . '\';
$controller->params = $this->params = unserialize(stripslashes(\'' . addslashes(serialize($this->params)) . '\'));
$controller->action = $this->action = unserialize(\'' . serialize($this->action) . '\');
$controller->data = $this->data = unserialize(stripslashes(\'' . addslashes(serialize($this->data)) . '\'));
$controller->theme = $this->theme = \'' . $this->theme . '\';
Router::setRequestInfo(array($this->params, array(\'base\' => $this->base, \'webroot\' => $this->webroot)));';
if ($useCallbacks == true) {
$file .= '
$controller->constructClasses();
$controller->Component->initialize($controller);
$controller->beforeFilter();
$controller->Component->startup($controller);';
}
$file .= '
$loadedHelpers = array();
$loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers);
foreach (array_keys($loadedHelpers) as $helper) {
$camelBackedHelper = Inflector::variable($helper);
${$camelBackedHelper} =& $loadedHelpers[$helper];
$this->loaded[$camelBackedHelper] =& ${$camelBackedHelper};
$this->{$helper} =& $loadedHelpers[$helper];
}
?>';
$content = preg_replace("/(<\\?xml)/", "<?php echo '$1';?>",$content);
$file .= $content;
return cache('views' . DS . $cache, $file, $timestamp);
}
エレメントキャッシュ
テーマ用のエレメントキャッシュもこれまたバグる・・ただ原因不明。
cakephpのバージョンをアップすればいいのかな。
テーマがあろうが無かろうが default の view を使ってしまう見たい。
ただ原則として key の値で pc やら mobile やらでエレメントを分ければいいと思うんだが。



