# `Zend_Cache` のフロントエンド

## Zend_Cache_Core

### 導入

`Zend_Cache_Core` は特別なフロントエンドであり、 モジュールのコアに含まれています。これはキャッシュフロントエンドの 基本機能を実装したものであり、他のクラスによってオーバーライドされます。

その他のフロントエンドクラスは、すべて `Zend_Cache_Core` を継承しており、以下で説明しているメソッドおよびオプションは 他のフロントエンドでも使用可能です。そのため、ここではこれらについての 詳しい説明は省略します。

### 使用可能なオプション

これらのオプションを、先の例で示したようにファクトリメソッドに渡します。

#### Core フロントエンドのオプション

オプション | データ型 | デフォルト値 | 説明
--- | --- | --- | ---
caching | Boolean | `TRUE` | キャッシングを有効/無効にします (キャッシュされたスクリプトのデバッグ時に有用です)。
cache_id_prefix | String | `NULL` | すべてのキャッシュ ID のプレフィックス。`NULL` を指定すると、 プレフィックスは使用しません。 キャッシュ ID のプレフィックスは、いわばキャッシュ内での名前空間です。 これによって、複数のアプリケーションやウェブサイトで キャッシュを共用できるようになります。 個々のアプリケーションやウェブサイトで それぞれ異なるキャッシュ ID プレフィックスを用いるようにすれば、 特定のキャッシュ ID をそれぞれの環境で使用できるようになります。
lifetime | Integer | 3600 | キャッシュの有効期間 (秒)。`NULL` を指定すると、有効期間が無期限となります。
logging | Boolean | `FALSE` | `TRUE` を指定すると、`Zend_Log` によるロギングが有効になります (しかし、処理速度は低下します)。
write_control | Boolean | `TRUE` | 書き込み制御を有効/無効にします (壊れたエントリを検出するため、 書き込んだ直後にそのキャッシュを読み込みます)。 writeControl を有効にすると、キャッシュの書き込みがやや遅くなりますが、 読み込みの速度は変わりません (これはキャッシュファイルが壊れているかどうかを調べるものですが、 完全に判断できるわけではありません)。
automatic_serialization | Boolean | `FALSE` | 自動シリアライズを有効/無効にします。 文字列でないデータを直接保存する際に使用します (しかし、処理速度は低下します)。
automatic_cleaning_factor | Integer | 10 | 自動クリーンアッププロセス (ガベージコレクタ) の設定を行います。 0 を指定すると、自動キャッシュクリーニングを行いません。 1 を指定すると計画的にキャッシュのクリーニングを行い、また x (1 より大きな整数) を指定すると、 x 回のキャッシュ書き込みについて 1 回の頻度で ランダムに自動クリーニングを行います。
ignore_user_abort | Boolean | `FALSE` | `TRUE` を指定すると、`save()` メソッド内で PHP の ignore_user_abort フラグを設定し、 キャッシュが破壊されることを防ぎます。

### 例

マニュアルのいちばんはじめのほうに、例を示しています。

もしキャッシュに文字列しか保存しないのなら ("automatic_serialization" オプションを使用すると boolean も保存できるので)、 このようにもう少しコンパクトに作成することが可能です。

    // すでに $cache が存在するものとします

    $id = 'myBigLoop'; //「キャッシュしたい内容」のキャッシュ ID

    if (!($data = $cache->load($id))) {
        // キャッシュが存在しませんでした

        $data = '';
        for ($i = 0; $i < 10000; $i++) {
            $data = $data . $i;
        }

        $cache->save($data);

    }

    // [...] $data を用いて何かをします (echo したり、何かに渡したりなど)

複数のブロックやデータのインスタンスをキャッシュしたい場合も、考え方は同じです。

    // 一意な ID を使用するようにしましょう
    $id1 = 'foo';
    $id2 = 'bar';

    // ブロック 1
    if (!($data = $cache->load($id1))) {
        // キャッシュが存在しませんでした

        $data = '';
        for ($i=0;$i<10000;$i++) {
            $data = $data . $i;
        }

        $cache->save($data);

    }
    echo($data);

    // これは、キャッシュ処理の影響を受けません
    echo('キャッシュされません !');

    // ブロック 2
    if (!($data = $cache->load($id2))) {
        // キャッシュが存在しませんでした

        $data = '';
        for ($i=0;$i<10000;$i++) {
            $data = $data . '!';
        }

        $cache->save($data);

    }
    echo($data);

特殊な値 (boolean 値に "automatic_serialization" オプションを指定したものなど) や空の文字列をキャッシュしたい場合は、 上で示したコンパクトな例を使用することはできません。 キャッシュレコードを正式に調べる必要があります。

    // コンパクトな構文
    // (空の文字列や boolean をキャッシュする場合はうまくいきません)
    if (!($data = $cache->load($id))) {

        // キャッシュが存在しませんでした

        // [...] $data を作成します

        $cache->save($data);

    }

    // $data に対して何らかの操作をします

    // [...]

    // 完全な構文 (どんな場合でも動作します)
    if (!($cache->test($id))) {

        // キャッシュが存在しませんでした

        // [...] $data を作成します

        $cache->save($data);

    } else {

        // キャッシュが見つかりました

        $data = $cache->load($id);

    }

    // $data に対して何らかの操作をします

## Zend_Cache_Frontend_Output

### 導入

`Zend_Cache_Frontend_Output` は、出力を横取りするフロントエンドです。 これは PHP の出力バッファリング処理を使いやすくしたもので、 `start()` メソッドと `end()` メソッドの間の出力を横取りします。

### 使用可能なオプション

`Zend_Cache_Core` のオプション以外に、 このフロントエンドが独自に使用するオプションはありません。

### 例

このマニュアルの冒頭に示した例とほとんど同じですが、少しだけ変更を加えています。

    // キャッシュが見つからなかった場合に、出力バッファリングが起動します
    if (!($cache->start('mypage'))) {

        // すべてをいつもどおりに出力しますoutput everything as usual
        echo 'Hello world! ';
        echo 'これはキャッシュされます ('.time().') ';

        $cache->end(); // 出力バッファリングを終了します

    }

    echo 'これはキャッシュされません ('.time().').';

この形式を使用すると、既存のプロジェクトに簡単に出力キャッシュ処理を追加することができます。 コードのリファクタリングもほとんど行わずにすませられるでしょう。

## Zend_Cache_Frontend_Function

### 導入

`Zend_Cache_Frontend_Function` は、関数コールの結果をキャッシュします。 `call()` というメソッドを保持しており、 関数名とパラメータを配列にしてこのメソッドに渡します。

### 使用可能なオプション

#### Function フロントエンドのオプション

オプション | データ型 | デフォルト値 | 説明
--- | --- | --- | ---
cache_by_default | Boolean | `TRUE` | `TRUE` の場合は、関数のコール結果がデフォルトでキャッシュされます。
cached_functions | Array |  | 常にキャッシュされる関数の名前。
non_cached_functions | Array |  | 決してキャッシュされない関数の名前。

### 例

`call()` 関数の使用法は、PHP の `call_user_func_array()` と同じです。

    $cache->call('veryExpensiveFunc', $params);

    // $params は配列です。
    // 例えば、veryExpensiveFunc(1, 'foo', 'bar') のコールをキャッシュするには
    // $cache->call('veryExpensiveFunc', array(1, 'foo', 'bar')) とします。

`Zend_Cache_Frontend_Function` は、 関数の返り値だけでなく関数内部での出力もキャッシュします。

`array()`、`echo()`、`empty()`、`eval()`、 `exit()`、`isset()`、`list()`、`print()` および `unset()` 以外なら、 任意の組み込み関数やユーザ定義関数を渡すことができます。

## Zend_Cache_Frontend_Class

### 導入

`Zend_Cache_Frontend_Class` は、`Zend_Cache_Frontend_Function` と異なり、オブジェクトおよびスタティックメソッドのコールをキャッシュします。

### 使用可能なオプション

#### Class フロントエンドのオプション

オプション | データ型 | デフォルト値 | 説明
--- | --- | --- | ---
cached_entity (必須) | Mixed |  | クラス名を設定すると、抽象クラスおよびスタティックコールをキャッシュします。 オブジェクトを設定すると、そのオブジェクトのメソッドをキャッシュします。
cache_by_default | Boolean | `TRUE` | `TRUE` を設定すると、デフォルトでキャッシュされます。
cached_methods | Array |  | 常にキャッシュされるメソッドの名前。
non_cached_methods | Array |  | 決してキャッシュされないメソッドの名前。

### 例

例えば、スタティックメソッドのコールをキャッシュするには次のようにします。

    class Test {

        // スタティックメソッド
        public static function foobar($param1, $param2) {
            echo "foobar_output($param1, $param2)";
            return "foobar_return($param1, $param2)";
        }

    }

    // [...]
    $frontendOptions = array(
        'cached_entity' => 'Test' // クラス名を指定します
    );
    // [...]

    // これはキャッシュされます
    $result = $cache->foobar('1', '2');

通常のメソッドのコールをキャッシュするには次のようにします。

    class Test {

        private $_string = 'hello !';

        public function foobar2($param1, $param2) {
            echo($this->_string);
            echo "foobar2_output($param1, $param2)";
            return "foobar2_return($param1, $param2)";
        }

    }

    // [...]
    $frontendOptions = array(
        'cached_entity' => new Test() // クラスのインスタンスを指定します
    );
    // [...]

    // これはキャッシュされます
    $result = $cache->foobar2('1', '2');

## Zend_Cache_Frontend_File

### 導入

`Zend_Cache_Frontend_File` は、マスタファイルの 「更新時刻」にもとづいて動作するフロントエンドです。 これは、例えば設定ファイルやテンプレートなどで有効に使えるでしょう。 複数のマスタファイルを使用することもできます。

例えば、XML の設定ファイルを使用しており、それが「設定オブジェクト」 (`Zend_Config` など) を返す関数でパースされるとしましょう。 `Zend_Cache_Frontend_File` を使用すると、その「設定オブジェクト」 をキャッシュすることができ (これにより、 XML ファイルを毎回パースする必要がなくなります)、さらに「マスタファイル」 との間で強力な依存性を保持することができます。そのため、XML 設定ファイルが更新されると、即時にキャッシュが無効になります。

### 使用可能なオプション

#### File フロントエンドのオプション

オプション | データ型 | デフォルト値 | 説明
--- | --- | --- | ---
master_file (非推奨) | String | '' | マスタファイルへのフルパス。
master_files | Array | `array()` | マスタファイル群へのフルパスの配列。
master_files_mode | String | `Zend_Cache_Frontend_File::MODE_OR` | `Zend_Cache_Frontend_File::MODE_AND` あるいは `Zend_Cache_Frontend_File::MODE_OR`。 `MODE_AND` の場合は、 すべてのマスタファイルにアクセスがあるまでキャッシュが無効化されません。 `MODE_OR` の場合は、 どれかひとつのマスタファイルにアクセスがあればキャッシュを無効化します。
ignore_missing_master_files | Boolean | `FALSE` | `TRUE` の場合は、マスタファイルが存在しない場合は無視します (それ以外の場合は例外が発生します)。

### 例

このフロントエンドの使用法は `Zend_Cache_Core` と同じです。 そのため、特に例は用意していません。唯一しなければならないことは、 ファクトリを使用する際に、バックエンドのオプションとして master_file を設定することだけです。

## Zend_Cache_Frontend_Page

### 導入

`Zend_Cache_Frontend_Page` は `Zend_Cache_Frontend_Output` と似ていますが、ページ全体をキャッシュする目的で設計されています。 `Zend_Cache_Frontend_Page` を使用して、 ページの一部だけをキャッシュすることはできません。

一方、「キャッシュ ID」は自動的に生成されます。この ID は、 `$_SERVER['REQUEST_URI']` および (オプションの設定によっては) `$_GET`、`$_POST`、`$_SESSION`、 `$_COOKIE`、`$_FILES` をもとにして生成されます。 さらに、ひとつのメソッド (`start()`) をコールするだけで使用できます。 `end()` は、ページの終了時に自動的にコールされます。

現時点ではまだ実装されていませんが、将来は HTTP conditional システムを追加する予定です。 これにより、ネットワークの帯域を節約できるようになります (キャッシュにヒットし、かつブラウザがそのバージョンを既に持っている場合に HTTP 304 Not Modified を送信するようにします)。

### 使用可能なオプション

#### Page フロントエンドのオプション

オプション | データ型 | デフォルト値 | 説明
--- | --- | --- | ---
http_conditional | Boolean | `FALSE` | http_conditional システムを使用します (現時点ではまだ実装されていません)。
debug_header | Boolean | `FALSE` | `TRUE` の場合は、キャッシュされた各ページの先頭に デバッグ用テキストが追加されます。

default_options

Array

`array(...説明を参照ください...)`

デフォルトのオプションを表す連想配列です。

- (boolean, デフォルトは `TRUE`) cache : `TRUE` の場合はキャッシュが有効になります。

- (boolean, デフォルトは `FALSE`) cache_with_get_variables : `TRUE` の場合は、`$_GET` 配列に変数が含まれていてもキャッシュがオンのままになります。

- (boolean, デフォルトは `FALSE`) cache_with_post_variables : `TRUE` の場合は、`$_POST` 配列に変数が含まれていてもキャッシュがオンのままになります。

- (boolean, デフォルトは `FALSE`) cache_with_session_variables : `TRUE` の場合は、`$_SESSION` 配列に変数が含まれていてもキャッシュがオンのままになります。

- (boolean, デフォルトは `FALSE`) cache_with_files_variables : `TRUE` の場合は、`$_FILES` 配列に変数が含まれていてもキャッシュがオンのままになります。

- (boolean, デフォルトは `FALSE`) cache_with_cookie_variables : `TRUE` の場合は、`$_COOKIE` 配列に変数が含まれていてもキャッシュがオンのままになります。

- (boolean, デフォルトは `TRUE`) make_id_with_get_variables : `TRUE` の場合は、キャッシュ ID が `$_GET` 配列の内容に依存するようになります。

- (boolean, デフォルトは `TRUE`) make_id_with_post_variables : `TRUE` の場合は、キャッシュ ID が `$_POST` 配列の内容に依存するようになります。

- (boolean, デフォルトは `TRUE`) make_id_with_session_variables : `TRUE` の場合は、キャッシュ ID が `$_SESSION` 配列の内容に依存するようになります。

- (boolean, デフォルトは `TRUE`) make_id_with_files_variables : `TRUE` の場合は、キャッシュ ID が `$_FILES` 配列の内容に依存するようになります。

- (boolean, デフォルトは `TRUE`) make_id_with_cookie_variables : `TRUE` の場合は、キャッシュ ID が `$_COOKIE` 配列の内容に依存するようになります。

- (int, デフォルトは `FALSE`) specific_lifetime : `FALSE` でない場合は、選択した正規表現に対して指定した有効期限を使用します。

- (配列, デフォルトは `array()`) tags : キャッシュレコード用のタグ。

- (int, デフォルトは `NULL`) priority : 優先度 (バックエンドが優先度をサポートしている場合)。

regexps | Array | `array()` | 特定の `REQUEST_URI` に対してのみ適用するオプションを設定する連想配列です。 キーが (PCRE の) 正規表現、対応する値は連想配列となります。 この連想配列には、正規表現が `$_SERVER['REQUEST_URI']` にマッチした場合に設定されるオプションを設定します (使用可能なオプションについては default_options を参照ください)。 複数の正規表現が `$_SERVER['REQUEST_URI']` にマッチした場合は、 一番最後にマッチしたもののみが使用されます。
memorize_headers | Array | `array()` | HTTP ヘッダ名に対応する文字列の配列です。 ここにあげられたヘッダがキャッシュデータとともに保存され、 キャッシュにヒットしたときにそれが "リプレイ" されます。

### 例

`Zend_Cache_Frontend_Page` の使用法は、きわめて簡単です。

    // [...] // require、設定そしてファクトリ

    $cache->start();
    // キャッシュにヒットした場合はその結果がブラウザに送信され、
    // 処理はここで停止します

    // ページの残りの部分 ...

もう少し複雑な例を見てみましょう。これは、起動ファイル (例えば `Zend_Controller` など) 内でキャッシュを集中管理する方法を示したものです。

    /*
     * キャッシュセクションの前には、あまり多くの行を書かないようにしましょう。
     * 例えば、処理速度を最適化するためには "require_once" や "Zend_Loader::loadClass"
     * をキャッシュセクションの後におくべきです。
     */

    $frontendOptions = array(
       'lifetime' => 7200,
       'debug_header' => true, // デバッグします
       'regexps' => array(
           // IndexController 全体をキャッシュします
           '^/$' => array('cache' => true),

           // IndexController 全体をキャッシュします
           '^/index/' => array('cache' => true),

           // ArticleController はキャッシュしません
           '^/article/' => array('cache' => false),

           // ……が、ArticleController の "view" アクションはキャッシュします
           '^/article/view/' => array(
               'cache' => true,

               // また、たとえ $_POST に何らかの変数がふくまれていてもキャッシュを行います
               'cache_with_post_variables' => true,

               // しかし、そのキャッシュは $_POST 配列に依存します
               'make_id_with_post_variables' => true
           )
       )
    );

    $backendOptions = array(
        'cache_dir' => '/tmp/'
    );

    // Zend_Cache_Frontend_Page オブジェクトを取得します
    $cache = Zend_Cache::factory('Page',
                                 'File',
                                 $frontendOptions,
                                 $backendOptions);

    $cache->start();
    // キャッシュにヒットした場合はその結果がブラウザに送信され、スクリプトの処理はここで停止します。

    // [...] 起動ファイルの終点 (これらの行は、キャッシュにヒットした場合は実行されません)

### キャンセル用のメソッド

設計上の理由から、場合によっては (HTTP 200 以外のコードを使用する場合など) 現在のキャッシュ処理をキャンセルする必要が生じることもあります。 そこで、このフロントエンド用に `cancel()` メソッドを用意しました。

    // [...] // require, configuration そして factory

    $cache->start();

    // [...]

    if ($someTest) {
        $cache->cancel();
        // [...]
    }

    // [...]