管理画面からプラグインを入れて有効にしたのに、公開側のページでは何も変わりませんでした。同じプラグインを入れたほかのサイトでは、すぐに効いています。ログインしたまま公開側のページを開いたら効くようになったので、キャッシュが怪しいと考えて調べました。
原因:管理画面と公開側のページで、キャッシュの扱いが違った
このサイトには、APCu を使うオブジェクトキャッシュ(wp-content/object-cache.php)が入っていました。中を読むと、次のような作りになっていました。
このオブジェクトキャッシュの作り
- 管理画面ではキャッシュを使わない(ふつうの DB の読み書きだけ)
- 公開側のページでは、読んだ値を APCu に期限なしで覚える
- ログインした人が公開側のページを開いたときだけ、APCu を全部消す
WordPress は、有効なプラグインの一覧(active_plugins)などの設定を、まとめてオブジェクトキャッシュに入れて使います。管理画面でプラグインを有効にすると、DB の値は変わります。ところが、公開側のページは APCu に覚えた古い一覧を使い続けるので、新しく有効にしたプラグインが読み込まれていませんでした。
確認のしかた
「プラグイン」の画面の「ドロップイン」に object-cache.php があれば、オブジェクトキャッシュを使っています。管理画面で変えた設定が公開側のページに出ないときは、ログインしていない状態でページを開いて確認、そのあとログインしたまま公開側のページを 1 回開き、もう一度ログインしていない状態で確認します。これで直るなら、オブジェクトキャッシュに古い値が残っていたということです。
直し方
すぐに直すなら、ログインしたまま公開側のページを 1 回開くだけです。ただ、毎回それを覚えておくのは大変なので、設定を変えたときにキャッシュを消す処理を足しました。管理画面ではこのオブジェクトキャッシュが読まれないので、APCu の関数を直接呼びます。
// プラグインの有効・無効や設定の保存のあとに、APCu のキャッシュを消す
// (管理画面と公開側のページで同じ APCu を使っている環境のときに効く)
function my_clear_apcu_after_change() {
if ( function_exists( 'apcu_clear_cache' ) ) {
apcu_clear_cache();
}
}
add_action( 'activated_plugin', 'my_clear_apcu_after_change' );
add_action( 'deactivated_plugin', 'my_clear_apcu_after_change' );
add_action( 'upgrader_process_complete', 'my_clear_apcu_after_change' );
サーバーによっては、PHP の動き方の都合で、管理画面と公開側のページで APCu を分けて持っていることがあります。その場合は上のコードでは消えないので、ログインしたまま公開側のページを開くやり方が確実です。
気をつけること
- オブジェクトキャッシュは、入れた本人も忘れがち。サイトを引き継いだら、まず「ドロップイン」を見ておく
- 期限なしで覚える作りは速い反面、こうした食い違いが起きやすい。期限を付けるか、変えたときに消す処理を必ずセットにする
- ページのキャッシュ(WP-Optimize など)とは別のものなので、ページのキャッシュを消しても直らない
