2011年05月11日

cakephp ビューキャッシュを極める

お願いします♪いいねとかつぶやいたりして下さい
 



※ 11月1日 PCサイトとスマふぉさいとの振り分け法追記。
※ 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);
}


core.php
1行コメントアウトして、 追記。
//Cache::config('default', array('engine' => 'File'));
	
Cache::config('default', array(
'engine' => 'File', //[required]
'duration'=> 3600, //[optional]
'probability'=> 100, //[optional]
'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
'prefix' => 'cake_', //[optional]  prefix every cache file with this string
'lock' => false, //[optional]  use file locking
'serialize' => 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 やらでエレメントを分ければいいと思うんだが。
関連するタグ: cakephp
あなたにとって有用な記事でしたか?是非ブックマークしておくことをおすすめします。
 




ライブラリを配布しちゃったり
webデザイン
Fireworks
HTMLコーディング
CSS
Dreamweaver
携帯サイト
webプログラム
PHP
正規表現
cakephp
MYSQL
javascript
webマーケティング
adwords
analytics
windows7
ショートカットキー
おすすめ情報
サイト
facebook
ライブラリ
配布
アプリ
iphone
ipad
サーバー
さくらサーバー
全ての記事を読む




トップ - 最新の記事一覧 - お問い合わせ