wp_cache_get()がfalseを返したらfoundでcache missか保存値かを分ける
公開日: 執筆:佐藤
WordPressのwp_cache_get()は、cacheに値がない場合も、保存されている値がfalseの場合も、戻り値がfalseになります。戻り値だけを条件式へ入れると、保存済みのfalseをcache missと誤認します。
第4引数の$foundを使ってください。$foundはkeyが見つかればtrue、見つからなければfalseになり、戻り値とは別にcacheの有無を示します。
戻り値とfoundは答える疑問が違う
WordPress 4.0のObject Cache APIでは、wp_cache_get()を次の引数で定義しています。
wp_cache_get( $key, $group = '', $force = false, &$found = null );
各引数の役割を分けます。
| 引数 | 役割 |
|---|---|
$key |
保存した値を識別するkey |
$group |
同じkeyを用途別に分けるgroup。空ならdefaultになる |
$force |
persistent cacheから取り直すようbackendへ求める指定 |
$found |
keyがcache内に存在したかを受け取る変数 |
戻り値は保存されていた値です。$foundは、その値が見つかったかどうかです。値の内容とcacheの状態を、一つのfalseへ押し込まないための引数だと考えると分かりやすくなります。
falseを保存できる処理ではfoundを必ず確認する
次は、外部連携を有効にするかどうかを調べた結果をcacheへ置く仮例です。
$found = false;
$active = wp_cache_get( 'external_service_active', 'satolab_settings', false, $found );
if ( ! $found ) {
$active = satolab_check_external_service();
wp_cache_set( 'external_service_active', $active, 'satolab_settings' );
}
if ( $active ) {
satolab_run_external_service();
}
satolab_check_external_service()がfalseを返し、その値を保存する場合でも、二回目の取得では$foundがtrueになります。したがって、同じ確認処理を繰り返しません。
次の書き方では、保存済みのfalseとcache missを分けられません。
$active = wp_cache_get( 'external_service_active', 'satolab_settings' );
if ( false === $active ) {
$active = satolab_check_external_service();
}
戻り値が必ず配列や文字列になる設計なら、falseをmissとして扱える場合もあります。それでも、保存できる値の範囲を関数の責任として決めておかないと、後からbooleanを保存した時点で判定が崩れます。
keyとgroupは保存時と取得時でそろえる
wp_cache_set()で保存した値は、同じ$keyと$groupを指定して取得します。keyが同じでもgroupが違えば別の値です。groupを省略するとdefaultになるため、保存側だけにgroupを書いた状態でもmissになります。
wp_cache_set( 'summary', $summary, 'satolab_reports' );
$found = false;
$summary = wp_cache_get( 'summary', 'satolab_reports', false, $found );
用途の異なる値を一つのgroupへ集めるより、pluginや機能の責任範囲が分かるgroup名を決めます。削除するときも、wp_cache_delete()へ同じkeyとgroupを渡します。
setとaddとreplaceは上書き条件が違う
Object Cache APIには、保存方法が三つあります。
| 関数 | 保存条件 |
|---|---|
wp_cache_set() |
keyの有無にかかわらず値を保存する |
wp_cache_add() |
keyがまだない場合だけ保存する |
wp_cache_replace() |
keyがすでにある場合だけ置き換える |
単に最新の計算結果へ更新するならwp_cache_set()を使います。先に保存された値を残したいならwp_cache_add()、存在確認済みの値だけを更新したいならwp_cache_replace()です。関数名ではなく、上書きを許すかどうかで選びます。
保存の成否を確認する必要がある処理では、それぞれの戻り値も確認してください。$foundが示すのは取得時の存在であり、直前の保存が成功したかどうかではありません。
default cacheはrequestをまたぐ保存を保証しない
WordPress 4.0の標準WP_Object_Cacheは、値をmemoryへ置き、PHPの処理が終わると失います。$expireも標準実装では使いません。persistent cacheの実装へ置き換えられている環境では、requestをまたいで値が残り、$forceや期限の扱いもbackendに依存します。
そのため、Object Cacheへ入れた値が次のrequestにも必ず残る前提では設計しません。消えたら元データから再生成できる値に限り、cacheを速さのための手段として使います。保存そのものが目的なら、databaseやfileなど、必要な耐久性を持つ保存先を選びます。
foundは権限確認やnonce確認の代わりにならない
$foundが答えるのは、cache keyが存在したかどうかだけです。管理画面から更新処理を実行してよい利用者か、正しい画面から送られたrequestかは答えません。
利用者の操作でcacheを更新または削除する処理では、権限とnonceを別に確認します。cacheの存在判定、requestの正当性、保存元データの正しさは、異なる問題です。
最初の一手は、wp_cache_get()の戻り値だけでmissを判定している箇所を探し、保存され得る値にfalseが含まれるかを確認することです。含まれるなら、第4引数の$foundを追加します。
関連記事

