Seo tools

Neo Inspiration

  • Search

    • About Me

      • inspi 改め
        jakk@webアーキテクト(自称)
        php,javascript,seoなど
        得意技は extract();



  • Categories

  • Ranking

  • Comments

  • Others


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

    を誰か教えてください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 Responses to “Smarty と cakePHP でキャッシュを効かす方法”

    1. tt Says:

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

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

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

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

    2. Jakk Says:

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

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

    Leave a Reply

    2008/11/22 07:00:39