̃Gg[͂ĂȃubN}[Nɒlj

PHP :: clearstatcache() - ファイルのステータスのキャッシュをクリアする



キャッシュ機構を実装する場合に注意が必要。

先日、どうしても重いクエリを実行しなければ表示できないページがあり、キャッシュ機構を自前実装して対応する案件があった。(DB設計に問題があるというのはおいといて)

仕様としては

  1. キャッシュファイルパスを引数にとり、キャッシュクラスを new する。
  2. ライフタイム(キャッシュ有効期限)をセットするメソッドを呼ぶ。
  3. キャッシュを取得するメソッドを呼ぶ。
    • キャッシュの生成時刻とライフタイムを比較し、ライフタイム以内ならキャッシュ内容を表示して終了。
    • ライフタイムを超過していたら、
      1. 空文字列を返却。
      2. アウトプットバッファリングを有効にしてコンテンツを取得し、キャッシュとして内容をセーブするメソッドを呼ぶ。
      3. 再びキャッシュを取得するメソッドを呼ぶ。


クラスの実装は割愛しますが、処理プロセスは以下のようになります。

<?php
$cache = new Cache('/path/to/cache');
$cache->setLifetime(CACHE_LIFETIME);
if ($c = $cache->get()) { // (*1)
    echo $c;
    exit;
}
 
ob_start();
?>
--------------------
キャッシュしたい内容
 :
 :
--------------------
<?php
$cache->save(ob_get_clean());
echo $cache->get(); // (*2)
?>


ここで注意しなければならないのは、Cache::get 内で clearstatcache() を呼ばないとライフタイムを超過した場合、(*1) と (*2) で空文字列が返却されます。
※. (*1)で空文字列が返るのは正しい動作ですが


getメソッドの実装

/**
 * @access public
 */
public function get()
{
    // ファイルのステータスのキャッシュをクリアする
    clearstatcache();
 
    if (is_readable($this->file) && (filemtime($this->file) + $this->lifetime) > time()) {
        return file_get_contents($this->file);
    } else {
        return '';
    }
}
$this→filenew した時の引数。例では、/path/to/cache
$this→lifetimesetLifetime()メソッドでセットしたライフタイム


キャッシュ有効期限の判定を

(filemtime(キャッシュファイル) + ライフタイム) > time()

としているのですが、clearstatcache() を呼ばないと、filemtime関数の返り値はキャッシュされ、同一スクリプト内では常に同じ値が返ってきます。マニュアルにも載っています。

なお、以下の関数も clearstatcache() を呼ばないとファイルのステータス関連が更新されないので注意が必要です。

lstat(), stat(), file_exists(), is_writable(), is_readable(), 
is_executable(), is_file(), is_dir(), is_link(), filectime(), 
fileatime(), filemtime(), fileinode(), filegroup(), fileowner(), 
filesize(), filetype(), fileperms() 



programming/php/etc/clearstatcache.txt