速くより近くのストレージシステムに必要なデータの二次コピーを持つことにより、 高価なリソースや低速なリソースの読み込みを行うためにキャッシュを使用できます。 たとえば、高価なクエリの結果や頻繁に変更されないリモートウェブサービスへのアクセスを キャッシュに格納することができます。キャッシュに保存されると、キャッシュからの読み込みは、 リモートリソースにアクセスよりもはるかに高速です。
CakePHP のキャッシュは、 Cache
クラスを使用します。このクラスは、
様々なキャッシュの実装を扱うための静的なインターフェイスや統一された API を提供します。
CakePHP には、いくつかのキャッシュエンジンが用意されていて、
独自のバックエンドを構築する必要な場合、シンプルなインターフェイスを提供します。
以下が、組み込みのキャッシュエンジンです。
File
File キャッシュはローカルファイルを使用するシンプルなキャッシュです。
最も遅いキャッシュエンジンで、アトミックな操作のための多くの機能を持ちません。
しかし、ディスクストレージは非常に安価なので、頻繁に書き込みが行なわれない
大きなオブジェクトや要素の保存はファイルに適しています。
Memcached
Memcached 拡張を使います。
Redis
phpredis 拡張を使います。
Redis は高速で、Memcached と同様の永続キャッシュシステム、アトミックな操作を提供します。
Apcu
APCu キャッシュは、PHP の APCu 拡張を使用します。
この拡張はオブジェクトを保存するためにウェブサーバー上の共有メモリーを使います。
これはとても高速で、かつアトミックな読み込み/書き込みの機能を提供することが可能になります。
Wincache
Wincache は Wincache 拡張を使います。
Wincache は APC と同様の機能とパフォーマンスを持ちますが、Windows と IIS に最適化されています。
Array
はすべてのデータを配列に保存します。
永続的なストレージを提供せず、test suites内での使用を想定しています。
Null
nullエンジンは実質何も保存せず、すべての読み込み操作を失敗させます。
あなたが選択したキャッシュエンジンに関わらず、
アプリケーションは Cake\Cache\Cache
とやり取りします。
アプリケーションは、ブート処理中に任意の数の「エンジン」を設定できます。 キャッシュエンジンの設定は、 config/app.php で定義されています。
最適なパフォーマンスを得るには、CakePHP では2つのキャッシュエンジンを定義する必要があります。
_cake_core_
は、ファイル構成の保存と、
国際化と地域化
ファイルの結果のパースに使用されます。
_cake_model_
は、アプリケーション上のモデルに対するスキーマの説明を保存するために使用されます。
複数のエンジン設定を使用することで、必要に応じてストレージを段階的に変更できます。 例えば、以下のように config/app.php に設定できます。
// ...
'Cache' => [
'short' => [
'className' => 'File',
'duration' => '+1 hours',
'path' => CACHE,
'prefix' => 'cake_short_'
],
// 完全な名前空間つきの名前を使用。
'long' => [
'className' => 'Cake\Cache\Engine\FileEngine',
'duration' => '+1 week',
'probability' => 100,
'path' => CACHE . 'long' . DS,
]
]
// ...
オプション設定は DSN を指定することもできます。 これは環境変数や PaaS プロバイダーと一緒に動作するときに便利です。
Cache::setConfig('short', [
'url' => 'memcached://user:password@cache-host/?timeout=3600&prefix=myapp_',
]);
DSN を使用するとき、追加のクエリー文字列要素としてパラメーターやオプションが定義できます。
実行時におけるキャッシュエンジンの設定もできます。
// 短い名前で
Cache::setConfig('short', [
'className' => 'File',
'duration' => '+1 hours',
'path' => CACHE,
'prefix' => 'cake_short_'
]);
// 完全な名前空間つきの名前を使用。
Cache::setConfig('long', [
'className' => 'Cake\Cache\Engine\FileEngine',
'duration' => '+1 week',
'probability' => 100,
'path' => CACHE . 'long' . DS,
]);
// オブジェクトで
$object = new FileEngine($config);
Cache::setConfig('other', $object);
これらのエンジン設定の名前 ('short' や 'long') は Cake\Cache\Cache::write()
と
Cake\Cache\Cache::read()
の $config
パラメーターとして使われます。
キャッシュエンジンを設定する場合は、次の構文を使用してクラス名を参照することができます。
// 省略名 (App\ または Cake 名前空間の中)
Cache::setConfig('long', ['className' => 'File']);
// プラグインの省略名
Cache::setConfig('long', ['className' => 'MyPlugin.SuperCache']);
// 完全な名前空間
Cache::setConfig('long', ['className' => 'Cake\Cache\Engine\FileEngine']);
// CacheEngineInterface を実装したオブジェクト
Cache::setConfig('long', ['className' => $myCache]);
注釈
FileEngine 使用時に、正しいパーミッションでのキャッシュファイルを指定して作成するには、
mask
オプションの設定が必要です。
各エンジンは次のオプションを受け入れます。
duration
このキャッシュ設定内のアイテムの存続期間を指定します。
strototime()
互換表現として指定されます。
groups
この設定に格納されているすべてのキーに関連付けられているグループまたは「タグ」のリスト。
キャッシュから完全なグループを削除するのに便利です。
prefix
すべてのエントリーの先頭に追加されます。
キースペースを別のキャッシュ設定または別のアプリケーションと共有する必要がある場合に適しています。
probability
キャッシュ GC クリーンアップの可能性。
0 に設定すると、 Cache::gc()
が自動的に呼び出されなくなります。
FileEngine は次のエンジン固有オプションを使用します。
isWindows
ホストがウインドウズであるかどうかで自動的に設定されます。
lock
ファイルを書き込む前にロックする必要があるかどうか。
mask
作成されたファイルに使用されるマスク。
path
キャッシュファイルを保存する場所へのパス。 デフォルトはシステムの一時ディレクトリです。
RedisEngine は次のエンジン固有オプションを使用します。
port
Redis サーバーが動作しているポート。
host
Redis サーバーが動作しているホスト。
database
接続に使用するデータベース番号。
password
Redis サーバーのパスワード。
persistent
Redis への永続的な接続を行うかどうか。
timeout
Redis の接続タイムアウト。
unix_socket
Redis の UNIX ソケットへのパス。
compress
データを圧縮するかどうか。
username
Memcache サーバーにアクセスするためのログイン名。
password
Memcache サーバーにアクセスするためのパスワード。
persistent
永続的な接続の名前。同じ永続的な値を使用するすべての設定は、
単一の基本接続を共有します。
serialize
データをシリアライズするために使用されるシリアライザエンジン。
利用可能なエンジンは php、igbinary、json です。
php のほかに、memcached 拡張は適切なシリアライザのサポートでコンパイルする必要があります。
servers
memcached サーバーの文字列または配列。配列の場合、MemcacheEngine
はそれらをプールとして使用します。
options
memcached クライアントの追加のオプション。オプション => 値 の配列でなければなりません。
\Memcached::OPT_*
定数をキーとして使用してください。
書き込み不可能なフォルダーに書き込む FileEngine
や、 RedisEngine
が Redis に
接続できないなど、エンジンが利用できない場合、エンジンは NullEngine
にフォールバックし、
ログ可能なエラーを引き起こします。これにより、キャッシュ障害のためにアプリケーションが
キャッチされない例外をスローするのを防ぎます。
fallback
設定キーを使ってキャッシュ設定を指定された設定にフォールバックするよう設定できます。
Cache::setConfig('redis', [
'className' => 'Redis',
'duration' => '+1 hours',
'prefix' => 'cake_redis_',
'host' => '127.0.0.1',
'port' => 6379,
'fallback' => 'default',
]);
Redis サーバーが予期せず失敗した場合、 redis
キャッシュ設定への書き込みは、
default
キャッシュ設定への書き込みにフォールバックします。このシナリオで default
キャッシュ設定への
書き込みも失敗した場合、 NullEngine
へ再び縮退運転し、キャッチされない例外をスローするのを防ぎます。
false
でキャッシュフォールバックを無効にすることができます。
Cache::setConfig('redis', [
'className' => 'Redis',
'duration' => '+1 hours',
'prefix' => 'cake_redis_',
'host' => '127.0.0.1',
'port' => 6379,
'fallback' => false
]);
フォールバックがない場合、キャッシュ障害は例外として発生します。
一度設定が作成されたら、変更することはできません。代わりに、
Cake\Cache\Cache::drop()
と Cake\Cache\Cache::config()
を使用して、設定を削除して再作成する必要があります。キャッシュエンジンを削除すると、設定が削除され、
アダプターが構築されていれば破棄されます。
Cache::write()
はキャッシュに $value を書き込みます。
この値は後で $key
で参照したり、削除したりすることができます。
オプションの設定を指定して、キャッシュを保存することもできます。
$config
を指定しない場合、デフォルトが使用されます。
Cache::write()
はあらゆるタイプのオブジェクトを格納することができ、
以下のようにモデルの結果を格納するのに理想的です。
$posts = Cache::read('posts');
if ($posts === null) {
$posts = $someService->getAllPosts();
Cache::write('posts', $posts);
}
Cache::write()
と Cache::read()
を使用して、データベースへのアクセスを減らし、
posts を取得しています。
注釈
CakePHP ORM で作成したクエリーの結果をキャッシュする場合は、 ロードされた結果をキャッシュする セクションで説明しているように、Query オブジェクトのビルトインキャッシュ機能を使用する方が良いです。
一度に複数のキャッシュキーを書き込む必要が出るかもしれません。
write()
を複数回呼び出すこともできますが、 writeMany()
は
CakePHP がより効率的なストレージ API を使用できるようにします。
例えば Memcached を使用する場合、 writeMany()
を使用して、
複数回のネットワーク接続を節約できます。
$result = Cache::writeMany([
'article-' . $slug => $article,
'article-' . $slug . '-comments' => $comments
]);
// $result は以下を含みます
['article-first-post' => true, 'article-first-post-comments' => true]
Cache::add()
を使用すると、キーがキャッシュに存在しない場合に、
アトミックにキーを値に設定することができます。
もし、キーがすでにキャッシュに存在する場合や、書き込みに失敗した場合は、
add()
は false
を返します:
// キーをロックとして機能するように設定する
$result = Cache::add($lockKey, true);
if (!$result) {
return;
}
// 一度に1つのプロセスしかアクティブにできないアクションを行う。
// ロックキーを外す。
Cache::delete($lockKey);
警告
ファイルベースのキャッシュは、アトミックライトをサポートしていません。
Cache を使用すると、Read-through キャッシュを簡単に行うことができます。 指定されたキャッシュキーが存在する場合、それが返されます。 キーが存在しない場合、呼び出し可能オブジェクトが呼び出され、結果がキャッシュに格納されます。
たとえば、リモートサービスコールの結果をキャッシュすることがよくあります。
あなたはこれをシンプルにするために remember()
を使うことができます。
class IssueService
{
public function allIssues($repo)
{
return Cache::remember($repo . '-issues', function () use ($repo) {
return $this->fetchAll($repo);
});
}
}
Cache::read()
は、 $key
配下に格納されたキャッシュされた値を
$config
から読み込むために使用されます。 $config
が null の場合、
デフォルトの設定が使用されます。 Cache::read()
は、有効なキャッシュであれば
キャッシュされた値を返し、キャッシュが期限切れになっているか存在しない場合は null
を返します。
キャッシュの内容は false と評価される可能性があるので、必ず厳密な比較演算子
===
または !==
を使用してください。
例:
$cloud = Cache::read('cloud');
if ($cloud !== null) {
return $cloud;
}
// クラウドデータを生成する
// ...
// キャッシュにデータを保存する
Cache::write('cloud', $cloud);
return $cloud;
short
という別のキャッシュ設定を使っている場合、
下記のように Cache::read()
と Cache::write()
に明記してください。
// デフォルトの代わりにshort からキー"cloud" を読み込む
$cloud = Cache::read('cloud', 'short');
if ($cloud === null) {
// cloudデータ生成
// ...
// デフォルトの代わりにshort でデータをキャッシュ保存
Cache::write('cloud', $cloud, 'short');
}
return $cloud;
一度に複数のキーを書き込んだ後、あなたは恐らくそれらを同様に読み込みたいでしょう。
read()
を複数回呼び出すこともできますが、 readMany()
は CakePHP が
より効率的なストレージ API を使用できるようにします。例えば Memcached を使用している場合、
readMany()
を使用して、複数回のネットワーク接続を節約できます。
$result = Cache::readMany([
'article-' . $slug,
'article-' . $slug . '-comments'
]);
// $result は以下を含みます
['article-first-post' => '...', 'article-first-post-comments' => '...']
Cache::delete()
を使うと、キャッシュされたオブジェクトをストアから完全に削除できます。
// キーの削除
Cache::delete('my_key');
4.4.0 以降、 RedisEngine
は deleteAsync()
メソッドも提供し、
UNLINK
オペレーションを使用してキャッシュキーを削除します:
Cache::pool('redis')->deleteAsync('my_key');
一度に複数のキーを書き込んだら、それらを削除したいかもしれません。
delete()
を複数回呼び出すこともできますが、 deleteMany()
は CakePHP が
より効率的なストレージ API を使用できるようにします。例えば Memcached を使用している場合、
deleteMany()
を使用して、複数回のネットワーク接続を節約できます。
$result = Cache::deleteMany([
'article-' . $slug,
'article-' . $slug . '-comments'
]);
// $result は以下を含みます
['article-first-post' => true, 'article-first-post-comments' => true]
キャッシュ設定から、すべてのキャッシュされた値を破棄します。Apcu、Memcached、Wincache などのエンジンでは、キャッシュ設定のプレフィックスを使用してキャッシュエントリーを削除します。 異なるキャッシュ設定には異なる接頭辞が付いていることを確認してください。
// すべてのキーをクリアする。
Cache::clear();
4.4.0 以降では、 RedisEngine
は clearBlocking()
メソッドも提供し、
UNLINK
オペレーションを使ってキャッシュキーを削除します:
Cache::pool('redis')->clearBlocking();
注釈
APCu と Wincache は、ウェブサーバーと CLI 用に分離されたキャッシュを使用するため、 別々にクリアする必要があります。(CLI ではウェブサーバーのキャッシュをクリアできません)
アプリケーション内のカウンターは、キャッシュに保存するのに適しています。 例として、コンテストの残りの「枠」の単純なカウントダウンをキャッシュに格納することができます。 Cache クラスは簡単な方法でカウンター値をインクリメント/デクリメントするアトミックな方法を公開しています。 競合のリスクを軽減し、同時に2人のユーザーが値を1つ下げて誤った値にする可能性があるため、 これらの値にはアトミック操作が重要です。
整数値を設定した後、 increment()
および decrement()
を使用して整数値を操作できます。
Cache::write('initial_count', 10);
// 設定した後に
Cache::decrement('initial_count');
// または
Cache::increment('initial_count');
注釈
インクリメントとデクリメントは FileEngine では機能しません。 代わりに、APCu、Wincache、Redis または Memcached を使用する必要があります。
まれにしか変更されない、またはキャッシュに大量の読み込みが行われるような結果をキャッシュすることによって、
アプリケーションのパフォーマンスを大幅に向上させることができます。
この完璧な例は、 Cake\ORM\Table::find()
の結果です。
この Query オブジェクトを使用すると、 cache()
メソッドを使用して結果をキャッシュできます。
詳細は、 ロードされた結果をキャッシュする セクションを参照してください。
たまに、複数のキャッシュエントリーを特定のグループまたは名前空間に属するようにマークしたい場合があります。 同じグループ内のすべてのエントリーで共有される情報が変更されるたびに、キーを大量に無効化したいというのは 一般的な要件です。これは、キャッシュ設定でグループを宣言することで可能です。
Cache::setConfig('site_home', [
'className' => 'Redis',
'duration' => '+999 days',
'groups' => ['comment', 'article']
]);
ホームページに生成された HTML をキャッシュに保存したいが、
コメントや投稿がデータベースに追加されるたびにこのキャッシュを自動的に無効にしたいとします。
comment
と article
グループを追加することで、このキャッシュ設定に保存されているキーに、
両方のグループ名で効果的にタグを付けできます。
たとえば、新しい投稿が追加されるたびに、 article
グループに関連付けられたすべてのエントリーを
削除するように Cache エンジンに指示できます。
// src/Model/Table/ArticlesTable.php
public function afterSave($event, $entity, $options = [])
{
if ($entity->isNew()) {
Cache::clearGroup('article', 'site_home');
}
}
groupConfigs()
を使用すると、グループと設定の間のマッピングを取得できます。
つまり、同じグループを持ちます。
// src/Model/Table/ArticlesTable.php
/**
* すべてのキャッシュ設定をクリアする前述の例のバリエーション
* 同じグループを持つ
*/
public function afterSave($event, $entity, $options = [])
{
if ($entity->isNew()) {
$configs = Cache::groupConfigs('article');
foreach ($configs['article'] as $config) {
Cache::clearGroup('article', $config);
}
}
}
グループは、同じエンジンと同じ接頭辞を使用して、すべてのキャッシュ設定で共有されます。 グループを使用していて、グループの削除を使用する場合は、すべての設定の共通プレフィックスを選択します。
キャッシュの有効期限に関連する問題を把握しようとするときに、
キャッシュの読み込みと書き込みをすべて無効にする必要があります。
enable()
と disable()
を使ってこれを行うことができます。
// すべてのキャッシュ読み取りとキャッシュ書き込みを無効にする。
Cache::disable();
無効にすると、すべての読み込みと書き込みは null
を返却します。
無効にすると、 enable()
を使用してキャッシュを再び有効にすることができます。
// すべてのキャッシュの読み込みと書き込みを再び有効にする。
Cache::enable();
もしキャッシュの状態を確認する必要がある場合は、 enabled()
を使用してください。
独自の Cache
エンジンは App\Cache\Engine
やプラグインの $plugin\Cache\Engine
の中に提供することができます。キャッシュエンジンはキャッシュディレクトリー内になければなりません。
MyCustomCacheEngine
という名前のキャッシュエンジンがあれば、
src/Cache/Engine/MyCustomCacheEngine.php に置かれます。また、プラグインの一部として、
plugins/MyPlugin/src/Cache/Engine/MyCustomCacheEngine.php に置かれます。
プラグインのキャッシュ設定は、プラグインのドット構文を使用する必要があります。
Cache::setConfig('custom', [
'className' => 'MyPlugin.MyCustomCache',
// ...
]);
カスタムキャッシュエンジンは、いくつかの抽象メソッドを定義するだけでなく、
いくつかの初期化メソッドを提供する Cake\Cache\CacheEngine
を拡張する必要があります。
キャッシュエンジンに必要な API は次のとおりです。
Cache で使用されるすべてのキャッシュエンジンの基本クラス。
成功時に boolean
キーの値をキャッシュに書き込み、データが正常にキャッシュされた場合は
true
を返し、失敗した場合は false
を返します。
キャッシュ値または失敗時に false
。
キャッシュからキーを読み取ります。
エントリーが期限切れまたは存在しないことを示す場合は false
を返します。
Boolean 成功時に true
キャッシュからキーを削除します。
エントリーが存在しなかったか、削除できなかったことを示す場合は false
を返します。
Boolean 成功時に true
キャッシュからすべてのキーを削除します。
$check が true
の場合、各値が実際に期限切れであることを検証する必要があります。
Boolean 成功時に true
同じグループに属するキャッシュからすべてのキーを削除します。
Boolean 成功時に true
キー配下の数字をデクリメントし、デクリメントされた値を返します。
Boolean 成功時に true
キー配下の数字をインクリメントし、インクリメントされた値を返します。