WordPressのプラグイン関数など、出力結果を取れない場合でもキャッシュさせる方法

このサイトではないんですが、別に設置したWordPressにRSSImportプラグインを入れてRSSフィードを表示させてみました。

設置しているのがあまり性能の良くないサーバなので、せめてこういったフィードの結果などはキャッシュさせておいて、1時間に1度程度リフレッシュするようにしようかと。多少なりともパフォーマンスが上がるかなと思いまして。

そこで手軽なところでPEAR::Cache_Lite(もちろん他の方法でもかまいませんが)を使って出力をキャッシュしようとしたのです。が、RSSImportには戻り値がなく、直接文字列が出力されてしまうので出力内容を得ることができないという非常事態に。

<?php RSSImport(5, 'RSSフィードのURL'); ?>

テンプレ内でこれを実行した瞬間にもう画面に出力されてしまうので、キャッシュしようがないのでした。これだとRSSImportは毎回実行されてしまいます。例えばWordPressの記事タイトルを得る wp_title の第2引数のように、直接出力するか戻り値のみ得られるようにするか選べればいいんですが、それっぽいオプションもないようですし… これについてはキャッシュするのを諦めるしかないかもです。

一旦、$str = RSSImport(…) みたいな感じで、出力結果を変数に入れることができればいいんだけどなあ… プラグインの中身は触りたくないしなあ… と思っていたらアッサリ見つかりました(笑)

 

ob(Output Buffering)関数を使う

<?php
ob_start();
RSSImport('RSSフィードのURL');
$str = ob_get_contents(); // RSSImportの結果を得る
ob_end_clean();
echo $str;
?>

これで、$strにRSSImport()の実行結果が取得できた上で、echoで出力できます。

まず、ob_start()でバッファリングを開始します。その後、echo(もしくはprint)で文字列を出力しようとしても内部バッファに格納され、実際に表示はされなくなります。

処理が終わったら内部バッファに溜め込んだ内容を ob_get_contents()で取り出すことができます。上記の例だと 4行目で$str に代入しています。

 ob_end_clean()で内部バッファの内容を出力させずにバッファリングを終了。

この例ではこの後キャッシュさせたいので変数格納してechoで内容を出力していますが、ob_end_clean()は使わず、ob_end_flush()で内部バッファの内容を出力してバッファリング終了することもできます。

 

キャッシュ処理を組み込む

あとはもはや蛇足って感じになってしまうと思いますが、PEAR::Cache_Liteを使ったキャッシングは以下みたいな感じになるかと思います。

<?php
require 'Cache/Lite.php';
$options = array(
'cacheDir' => '/hogehoge/cache/',
'lifeTime' => 3600, // 1 hour
);
$cacheName = 'CACHE_HOGEHOGE'; // キャッシュの名前
$cache = new Cache_Lite($options);
if ($cacheData = $cache->get($cacheName)) {
// キャッシュされている場合
echo $cacheData;
} else {
// 未キャッシュ&有効期限切れの場合
ob_start();
RSSImport('RSSフィードのURL');
$str = ob_get_contents(); // RSSImportの結果を得る
ob_end_clean();
echo $str;
$cache->save($str, cacheName); // キャッシュする
}
?>

 キャッシュされていればそのままecho出力、そうでなければob_start()以降のバッファリングを行った上でecho出力しつつキャッシュに保存、という流れです。もちろん、RSSImportだけに限らず、この手の戻り値のないでも同様にして使えますね。また、WordPress限定ってわけでなく、PHP全般的に利用可能です。

 

僕は会社辞めてからPHP使い始めて、ずっと使ってるわけではないものの、もうPHP歴2年くらいにはなるんですが、未だにこういうテクニック(?)とかはあまり良く知らないままだったりするので、もっと勉強しないとなあ…