キャッシュを作ってみよう。
篠原 隆司
アフィリエイト広告を利用しています
このページの内容が役に立ったら X (旧twitter) でフォローして頂けると励みになります
挨拶や報告は無しで大丈夫です
PHP高速化のために、ページ内容をデータベースやファイルにキャッシュする方法って色々紹介されてますね。
ってことで、今さらなんかなーって思いつつも。
実は私は、他ブログやニュースなどで、色々なキャッシュ方法を見聞きしてますが、実際に使ったことはありません。
「こういうのがあるよー」ってことを知っている程度です。
なぜか?って。
だって、自分でキャッシュの仕組みを作っちゃってたから。
では、コードの前に特徴から。
キャッシュの保存先はデータベースです。
最初は、ファイルベースでを作ってたんだけど、数万ページを超えるようなサイトだと、キャッシュファイルだけでもかなりの数になり、しかもFTPしか使えない状況だと大変なことになってきてたので、データベースに切り替えました。
キャッシュは、ページの任意の範囲で行えます。
ログイン機能など、ユーザーごとに微妙に表示内容の異なるサイトで威力を発揮します。
ヘッダーだけキャッシュ、内容だけキャッシュなど、キャッシュできる範囲は自由です。
もちろん、ページまるごとキャッシュも可能です。
1箇所のキャッシュで、任意の数の値をキャッシュできます。
キャッシュ用の変数は配列です。
ページ内容だけでなく、時間、商品名、説明文などなど、配列なので、好きなだけセットしてください。
例えば、body部はまるごと、meta keywordや、meta descriptionは、個別にキャッシュしたいなどに対応できます。
●データベースにテーブルを作成する。
CREATE TABLE IF NOT EXISTS `AultaCacheData` ( `CacheId` varchar(30) NOT NULL COMMENT 'キャッシュID', `CacheData` mediumtext NOT NULL, `CacheDatetime` datetime NOT NULL, PRIMARY KEY (`CacheId`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Aultaキャッシュ';
●定数宣言
// キャッシュ機能の有効・無効
define('CA_FILE_CACHE_ON', true);
●キャッシュからロードする
/*
* DBからキャッシュデータをロードする
* $cacheId : キャッシュID
* $expire : 有効期限(ミリ秒)
*/
function loadCacheDb($cacheId, $expire = 31536000){
// 戻り値の初期化
$returnData = array(
'isLoaded' => false // キャッシュから正常に読込みした
, 'timeStamp' => 0 // キャッシュファイルのタイムスタンプ(秒)
, 'header' => array() // ヘッダ
, 'data' => array() // データ
);
// 開発時などは CA_FILE_CACHE_ON = false でキャッシュを無効化
if ( ! CA_FILE_CACHE_ON) return $returnData;
// キャッシュのチェック
$result = dbGetFields(
"select CacheData, CacheDatetime from AultaCacheData"
. " where CacheId = '" . dbRealEscape($cacheId) . "'"
);
if ($result !== false){ // キャッシュファイルが存在する
$t = strtotime($result['CacheDatetime']);
if ($t > (time() - $expire)){ // タイムスタンプが有効期限以内なら
$returnData = (array)json_decode($result['CacheData'], true);
$returnData['timeStamp'] = $t; // ファイルのタイムスタンプをセット
$returnData['isLoaded'] = true;
}
}
return $returnData;
}
●キャッシュに書き込む
/* * キャッシュをDBに登録する * $cacheId : キャッシュID * $content : キャッシュする内容(配列) */ function saveCacheDb($cacheId, &$cacheData){ unset($cacheData['isLoaded']); unset($cacheData['timeStamp']); dbRunSql( "replace into AultaCacheData (CacheId, CacheData, CacheDatetime)" . " values (" . " '" . dbRealEscape($cacheId) . "'" . ", '" . dbRealEscape(json_encode($cacheData)) . "'" . ", now()" . ")" ); }
●●使用例
$isCreate = true;
$cacheId = 'URLや任意の文字など、識別するためのキー';
$data = loadCacheDb($cacheId, (12 * 3600));
if ($data['isLoaded']){ // キャッシュが見つかり、有効期限内
$isCreate = false;
} else { // キャッシュが無いので作成する。
$data = array(
'header' => array()
'data' => array()
);
~~~~~
$dataにキャッシュ内容をセットする。
$data['header']、$data['data']に、キャッシュしたい内容を放り込んでいく。
データベースには、$data配列のまま保存し、配列のまま取り出すので、好きなように値をセットできます。
~~~~~
saveCacheDb($cacheId, $dataContentInfo);
}
サンプル作る途中で、ちょこっと端折ったけど、ページが随時更新されるコミュニティ系のサイトなんかだと、最終の投稿日を「header」に入れておいて、ロード時に、データベース側の最終更新日時と突き合わせたほうが良いと思います。
あーー!!
書き終えて気づいた。。。
dbRunSql() と dbGetFields() と dbRealEscape() は、独自関数でした。
とりあえず、
http://blog.aulta.net/2008/08/10/utilityphp-%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E6%A5%BD%E3%81%AB%E3%81%99%E3%82%8B-function/
を読んでください。
その後、変更したり、追加したメソッドもあるから、はてなダのほうには、また後日載せます。