Smarty と cakePHP でキャッシュを効かす方法 2

を誰か教えてくださいorz

自分なりの対策をした結果だけ書いておきますが、
正しいやり方ではないと思っていることだけは明記しておきます。

cake のキャッシュを使う

のはできません。
なぜなら cake のキャッシュは cake の Viewの最後に renderCache して
書き出してるわけで、
そもそも smarty を使うと controller.php から view.php じゃなくて
smarty.php (ファイル名は人によって違うけど)に飛ぶので
読み込むことすらしません。

Smarty のキャッシュを使う

と、エラーになります。。。
具体的には missing_controller しかもなぜか 「image コントローラがありません」
といわれます。

core.write_cache_file みたいな smarty のコアファイルまで触らないといけなかったので
くじけましたが、
おそらく 画像のキャッシュを取るときにあーだこーだやってこのエラーになる気がします。

ちなみに render のトレースをすると compornent ごとにキャッシュを作っていて、
(index.tpl だけじゃなく、中の compornent ごとにキャッシュファイルを作る)
この部分もいちいち missing_controller になるようです。

さらに、極めつけは持ってくるのは ***.tpl のキャッシュなので
URLによって変化するとか そんなこともないし、
image のとこだけ対応できても無駄っぽいですし。

じゃあどうするか。。。

cake/basic.php なんてコアライブラリに function cache なんてものが入っていたので、
なんだこりゃとみてみたら、どうも controller でキャッシュを取れるようになっているみたいです。

ということで使ってみます。

・・・・ Arrayは使えませんか

ってよくみたら

$data = join(”, $data);

とかなってるし!
グルーなしですか。。。

仕方ないので basic.php を書き直す orz

function file_put_contents

$data = join(”, $data);

$data = serialize($data);
に書き換えて

function file_get_contents

return
の前に
$data = unserialize($data);
を書き足してみました。

・・・動いた!(クララが立った以上の感動;;)

画面キャッシュじゃなくて 変数キャッシュになっちゃいましたが、
レスポンスが圧倒的に早くなりました。
というのも、DBアクセスの ORマッパーがボトルネックだったのは
目に見えていたから。

丁寧に unbind していてもやっぱり ビタのSQL直書きにはかなわないですからねぇ。。

ちなみにやっぱりコアライブラリをいじるのは気持ち悪いので外だししておきました。
(一番下に出しておきます。)

使い方

controller の頭で

vendor(‘cachecreater’);

を書いておいて

$url = “”; //キャッシュファイルの名前
$this->cache = new CacheCreater(); 
$chk = $this->cache->cache_check($url); //キャッシュがあったらキャッシュデータを、なければnull
$this->cache->cache_create($url,$data); //$url というキャッシュファイルに $data の変数(配列でOK)を格納

まあ実用的には

$url = “引数_引数_引数.txt”; //キャッシュファイルの名前(引数全部を入れておけばIdごとにキャッシュできる)
$this->cache = new CacheCreater(); 
$chk = $this->cache->cache_check($url);

if(!isset($chk)){
ちゃんと処理する
最後にキャッシュに書き込む
$this->cache->cache_create($url,$data);
$this->set(‘cache’,$data);

}else{
$this->set(‘cache’,$chk);
}

こんなかんじで。

ちなみに動的に model が更新されたらキャッシュを消すとかは
今リアルタイムで検討中です。。。

<?php
class CacheCreater
{
var $expires = ‘+1 day’;  //これでキャッシュ保持は1日
var $target = ‘cache’;   //WEBROOT か tmp/cache にするか。
var $p = “orgcache/”; //tmp/cache/の下のどのフォルダに詰め込むか。

function cache_check($req=null){
$path = $this->p.$a.”.txt”;

return $this->_cache($path,null,$this->expires,$this->target);
}

function cache_create($req=null,$data){
$path = $this->p.$a.”.txt”;

$this->_cache($path,$data,$this->expires,$this->target);

return true;
}

function _file_get_contents($fileName, $useIncludePath = false){
$res=fopen($fileName, ‘rb’, $useIncludePath);

if ($res === false) {
trigger_error(‘file_get_contents() failed to open stream: No such file or directory’, E_USER_WARNING);
return false;
}
clearstatcache();

if ($fileSize = @filesize($fileName)) {
$data = fread($res, $fileSize);
} else {
$data = ”;

while(!feof($res)) {
$data .= fread($res, 8192);
}
}
$data = unserialize($data);

return $data;
}

function _file_put_contents($fileName, $data) {
$data = serialize($data);
$res = @fopen($fileName, ‘w+b’);
if ($res) {
$write = @fwrite($res, $data);
if($write === false) {
return false;
} else {
return $write;
}
}
}

function _cache($path, $data = null, $expires = ‘+1 day’, $target = ‘cache’) {
$now = time();
if (!is_numeric($expires)) {
$expires = strtotime($expires, $now);
}

switch(strtolower($target)) {
case ‘cache’:
$filename = CACHE . $path;
break;
case ‘public’:
$filename = WWW_ROOT . $path;
break;
}

$timediff = $expires – $now;
$filetime = false;
if(file_exists($filename)) {
$filetime = @filemtime($filename);
}

if ($data === null) {
if (file_exists($filename) && $filetime !== false) {
if ($filetime + $timediff < $now) { @unlink($filename); } else { $data = $this->file_get_contents($filename);
}
}
} else {
$this->file_put_contents($filename, $data);
}
return $data;
}

}
?>

2 thoughts on “Smarty と cakePHP でキャッシュを効かす方法

  1. Reply tt 10月 2,2007 9:45 PM

    >具体的には missing_controller しかもなぜか
    >「image コントローラがありません」
    >といわれます。

    遅レスですが、ない画像を読み込むとmod_rewriteがcakeを走らせてしまい、エラーになります。

    例)
    webroot/images/not_exist_image.jpgにアクセス

    ImagesControllerのnot_exist_image.jpgアクションを実行しようとする。

  2. Reply Jakk 10月 3,2007 9:57 AM

    ありがとうございます!
    仕組み的にはそんな感じなんだろうとは思っていたんですが、
    ソースだけで判断できなくて、
    という状況だったので、教えて頂いて助かりました。

    .htaccess の設定だけでできそうな予感ですね。
    ちょっと試してみたいと思います。

Leave a Reply