『CakePHP』を使ってみる 〜13〜 Cache を使う
今回は RSSHelper について試したことを書こうかと思ったけど
あまり思い通りの結果にならなくなってしまったので諦めて Cache についてメモ。
RSSHelper について良さそうな感じでまとまっていたのは以下です。
ブログのエントリをキャッシュしてみる
リファレンスの付録で作ったブログの個別エントリをキャッシュしてみるテスト。
ここで作った entry という アクションをコピーして cache というアクションを作ってみる。
<?php class PostsController extends AppController { var $name = 'Posts'; var $uses = array('Tag','Post'); function cache($id) { $post = $this->Post->findById($id); $this->postTitle = h($post['Post']['title']); $this->set('post', $post); } } ?>
とりあえずこれがベース。ここに手を加えていく。
Cache を使うための設定
CAKEPHP.jpのドキュメント和訳を参考にしよう、と思ったら 1.2 では早速設定項目が変わっていた。
- 1.1系 - define ('CACHE_CHECK', true);
- 1.2系 - Configure::write('Cache.check', true);
こんなカンジっぽい。
1.特定のエントリだけキャッシュ
エントリの id が 1 と 3 のものだけキャッシュするようにしてみる。
unixタイムを表示させて動作を確認してみることに。
とりあえず1時間キャッシュ。
- /home/theworld/cake/project/tutorial/controllers/posts_controller.php
<?php class PostsController extends AppController { var $name = 'Posts'; var $uses = array('Tag','Post'); var $helpers = array('Cache'); // 追加 var $cacheAction = array( // 追加 'posts/cache/1/' => 3600, 'posts/cache/3/' => 3600 ); function cache($id) { $time = time(); $post = $this->Post->findById($id); $this->postTitle = h($post['Post']['title']); $time = time(); $this->set('time', $time); $this->set('post', $post); } } ?>
3600のところは秒数での指定。60*60にしたらエラーになってしまった。
- /home/theworld/cake/project/tutorial/views/posts
<h1><?php echo $post['Post']['title']?></h1> <p>created on <?php echo $post['Post']['created']?></p> <p><?php echo $post['Post']['body']?></p> <p>now:<?php echo $time?> <p>
- キャッシュあり: http://lab.theworld.jp/cakephp/tutorial/posts/cache/1/
- キャッシュなし: http://lab.theworld.jp/cakephp/tutorial/posts/cache/2/
アクセスしてもらえればわかりますけど、それぞれうまくいきました。
キャッシュありの方は、「now」の項目が変化しますが、なしの方は変化しません。
キャッシュファイルは、tmpに作られています。
- /home/theworld/cake/project/tutorial/tmp/cache/views
作られたキャッシュファイルを開いてみると以下のような風になっていました。
ちょっと長いです。
<!--cachetime:1205505639--><?php App::import('Controller', 'Posts'); App::import('Model'); $this->controller = new PostsController(); $this->controller->plugin = ''; $this->controller->_initComponents(); $this->helpers = unserialize('a:3:{i:0;s:5:"Cache";i:1;s:4:"Html";i:2;s:4:"Form";}'); $this->base = '/cakephp/tutorial'; $this->layout = 'default'; $this->webroot = '/cakephp/tutorial/'; $this->here = '/cakephp/tutorial/posts/cache/1/'; $this->namedArgs = ''; $this->argSeparator = ''; $this->params = unserialize(stripslashes('a:10:{s:4:\"pass\";a:1:{i:0;s:1:\"1\";}s:5:\"named\";a:0:{}s:10:\"controller\";s:5:\"posts\";s:6:\"action\";s:5:\"cache\";s:6:\"plugin\";N;s:4:\"form\";a:0:{}s:3:\"url\";a:1:{s:3:\"url\";s:14:\"posts/cache/1/\";}s:4:\"bare\";i:0;s:11:\"webservices\";N;s:6:\"models\";a:2:{i:0;s:3:\"Tag\";i:1;s:4:\"Post\";}}')); $this->action = unserialize('s:5:"cache";'); $this->data = unserialize(stripslashes('N;')); $this->themeWeb = ''; $this->plugin = ''; Router::setRequestInfo(array($this->params, array('base' => $this->base, 'webroot' => $this->webroot))); $loadedHelpers = array(); $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers); foreach (array_keys($loadedHelpers) as $helper) { $replace = strtolower(substr($helper, 0, 1)); $camelBackedHelper = preg_replace('/\w/', $replace, $helper, 1); ${$camelBackedHelper} =& $loadedHelpers[$helper]; if (isset(${$camelBackedHelper}->helpers) && is_array(${$camelBackedHelper}->helpers)) { foreach (${$camelBackedHelper}->helpers as $subHelper) { ${$camelBackedHelper}->{$subHelper} =& $loadedHelpers[$subHelper]; } } $this->loaded[$camelBackedHelper] = (${$camelBackedHelper}); } ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title> CakePHP: the rapid development php framework: Posts </title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><link href="/cakephp/tutorial/favicon.ico" type="image/x-icon" rel="icon"/><link href="/cakephp/tutorial/favicon.ico" type="image/x-icon" rel="shortcut icon"/><link rel="stylesheet" type="text/css" href="/cakephp/tutorial/css/cake.generic.css" /></head> <body> <div id="container"> <div id="header"> <h1><a href="http://cakephp.org">CakePHP: the rapid development php framework</a></h1> </div> <div id="content"> <h1>The title</h1> <p>created on 2008-02-27 11:21:08</p> <p>This is the post body.</p> <p>now:1205502039 <p> </div> <div id="footer"> <a href="http://www.cakephp.org/" target="_new"><img src="/cakephp/tutorial/img/cake.power.gif" alt="CakePHP: the rapid development php framework" border="0" /></a> </div> </div> </body> </html>
2.特定のアクションをキャッシュ
引数で分けずにそのアクションを全てキャッシュする場合。
とりあえず、キャッシュフォルダのデータは消しておく。
- /home/theworld/cake/project/tutorial/controllers/posts_controller.php
<?php class PostsController extends AppController { var $name = 'Posts'; var $uses = array('Tag','Post'); var $helpers = array('Cache'); // 追加 var $cacheAction = array( // 追加 'posts/cache/' => 3600, ); function cache($id) { $time = time(); $post = $this->Post->findById($id); $this->postTitle = h($post['Post']['title']); $time = time(); $this->set('time', $time); $this->set('post', $post); } } ?>
- キャッシュあり: http://lab.theworld.jp/cakephp/tutorial/posts/cache/1/
- キャッシュあり: http://lab.theworld.jp/cakephp/tutorial/posts/cache/2/
両方ともキャッシュされた。
3.全てのアクションをキャッシュ
全てのアクションをキャッシュすることもできるとのこと。
でも、自分の使い方だとそういうことはしなそう。
var $cacheAction = 3600;
こんなカンジでアクションを指定せず時間だけ指定すれば OK。
4.テンプレートの一部分だけキャッシュ
テンプレートの一部分だけキャッシュすることも可能とのこと。
逆に言えば、一部だけ動的にできるということ。
このような使い方は、例えばエントリのカウンタだけはキャッシュしないみたいなことが想定できるかな。
キャッシュさせたくない部分を
作ったthtmlに手を加えてみる。
<h1><?php echo $post['Post']['title']?></h1> <p>created on <?php echo $post['Post']['created']?></p> <p><?php echo $post['Post']['body']?></p> <p>now:<cake:nocache><?php echo $time?></cake:nocache> <p>
これで、nowの項目だけ動的に動いていれば OK。
コントローラの記述は「2.特定のアクションをキャッシュ」のものに戻す。
できた!と思いきや、2回目のアクセスではエラーになってしまう。
Notice (8): Undefined variable: time [APP/tmp/cache/views/_cakephp_tutorial_posts_cache_1_.php, line 56]
うーん、なんでだろう?
$time のデータが定義されてないっていわれているけど…。
また後で検証してみる。