WordPress の表示速度を上げる手段のひとつに、永続オブジェクトキャッシュがあります。レンタルサーバーの多くは PHP 拡張の APCu を搭載しているので、Redis や Memcached を用意しなくても始められます。
ただし、永続オブジェクトキャッシュには「DB を書き換えたのに画面が古いまま」という落とし穴があります。この記事では、APCu Manager プラグインを使った設定手順と、実際に起きたトラブルの原因と対処をまとめます。
永続オブジェクトキャッシュとは
WordPress は get_post() や get_option() の結果をオブジェクトキャッシュに保存し、同じデータを何度も DB に問い合わせないようにしています。標準のオブジェクトキャッシュは 1 回のリクエストの中だけで有効で、リクエストが終わると消えます。
永続オブジェクトキャッシュは、この保存先をサーバーのメモリ(APCu、Redis、Memcached など)に置き換えます。次のリクエストでもキャッシュが残るので、DB へのクエリが減り、ページの生成が速くなります。
置き換えは wp-content/object-cache.php というドロップインファイルで行います。WordPress は起動の早い段階でこのファイルを読み込み、キャッシュ関数(wp_cache_get() など)を差し替えます。プラグインやテーマより前に読み込まれるので、functions.php に書いて代用することはできません。
ページキャッシュとの違い
キャッシュには種類があり、消し方もそれぞれ違います。混同すると、消すべきキャッシュを消せずに時間を使うことになります。
| 種類 | 保存するもの | 例 |
|---|---|---|
| オブジェクトキャッシュ | DB の問い合わせ結果(投稿、オプション、transient など) | APCu、Redis、Memcached |
| ページキャッシュ | 生成済みの HTML | サーバーのキャッシュ機能、LiteSpeed Cache の LSCache |
| OPcode キャッシュ | PHP のコンパイル結果 | OPcache |
管理画面の編集画面に古い本文が出るなら、疑うべきはページキャッシュではなくオブジェクトキャッシュです。管理画面は通常ページキャッシュの対象外だからです。
設定前に確認すること
管理画面の「ツール → サイトヘルス」を開きます。永続オブジェクトキャッシュを使っていない場合、「永続オブジェクトキャッシュを使用してください」という項目が出て、サーバーが対応しているキャッシュの種類(APCu、Redis など)が表示されます。ここに APCu があれば利用できます。
あわせて、wp-content/ に object-cache.php がすでに置かれていないか確認してください。別のプラグインや以前の作業で置いたものが残っていることがあります。
APCu Manager 4.6.1 の動作要件は WordPress 6.4 以上、PHP 8.2 以上です。
APCu Manager で設定する
APCu を使うには、プラグイン「APCu Manager」を導入します。
APCu Manager APCu の統計情報と管理を WordPress 管理ダッシュボードで直接行えます。 続きを読むAPCu Manager は、WordPress 6.x で追加された wp_cache_get_multiple()、wp_cache_flush_runtime()、wp_cache_flush_group() などの関数を実装したドロップインと、管理画面からの操作をまとめて提供します。
- 「プラグイン → 新規追加」で APCu Manager を検索し、インストールして有効化する
- APCu Manager の設定画面で、オブジェクトキャッシュを有効にする(ドロップインが
wp-content/object-cache.phpに配置される) - 同じ設定画面で、管理バーのショートカットを有効にする(管理バーに「APCu ➜ Delete All」が表示される)
- サイトヘルスを開き直し、永続オブジェクトキャッシュの項目が消えていることを確認する
APCu Manager の画面では、ヒット率や空きメモリの推移、キャッシュされているオブジェクトの一覧と個別削除も確認できます。
APCu Manager は、複数台のサーバーで PHP を動かす構成(クラスタ環境)には対応していません。APCu はサーバーごとのメモリなので、サーバー間でキャッシュが共有されないためです。
自作のドロップインから移行する場合
すでに自作の object-cache.php を使っているなら、次の順で入れ替えます。
- 後述の「キャッシュを全削除する方法」で、APCu を全削除する
- 自作の
object-cache.phpを削除する - APCu Manager をインストールし、上の手順で設定する
functions.phpにsave_postなどでキャッシュを全削除する処理をあれば削除する
LiteSpeed Cache などのプラグインにも、オブジェクトキャッシュの機能があります。これを有効にすると object-cache.php を上書きしようとして衝突するので、オフのままにしておきます。
DB を直接書き換えると、画面が古いままになる
永続オブジェクトキャッシュを入れて、最初につまずきやすいのがここです。
WordPress の画面や API(wp_update_post() など)から投稿を保存すると、本体が clean_post_cache() を呼んで、その投稿のキャッシュを消します。保存のたびにキャッシュを全削除するコードを functions.php に書く必要はありません。
問題は、WordPress を通さずに DB を書き換えた場合です。
- Better Search Replace などの一括置換プラグイン
- phpMyAdmin での直接編集
- サイト移行プラグインでのインポート
$wpdb->query()で直接 UPDATE する自作コード
これらはキャッシュを消す処理を通らないので、DB は新しい値になっていても、キャッシュには古い値が残ります。永続オブジェクトキャッシュのデータには有効期限がないことが多く、消すまで古い値が表示され続けます。
実際に起きた例です。Better Search Replace で一括置換したところ、phpMyAdmin では置換後の値になっているのに、編集画面では置換前の本文が表示されました。ブラウザを替えて再ログインしても変わりません。もう一度置換を実行すると「0 cells changed」と表示され、置換が効いていないように見えました。実際には置換は済んでいて、永続オブジェクトキャッシュが古い本文を返していただけでした。
キャッシュを全削除する方法
管理バーから消す
APCu Manager を使っているなら、管理バーの「APCu ➜ Delete All」を押せば全削除できます。DB を直接書き換えた後は、これを押す習慣をつけておくと安全です。
WP-CLI では APCu を消せない
wp cache flush は、Redis や Memcached なら効きますが、APCu には効きません。APCu のメモリは PHP の実行環境ごとに分かれていて、コマンドラインの PHP から Web サーバー側の APCu には届かないからです。APCu を消すときは、Web 経由のリクエストで wp_cache_flush() を呼びます。
自作コードで DB を直接書き換えるときの対策
プラグインやテーマで $wpdb から直接更新する場合は、処理の最後でキャッシュを消します。永続オブジェクトキャッシュを使っていないときは不要なので、wp_using_ext_object_cache() で判定します。
if ( wp_using_ext_object_cache() ) {
wp_cache_flush();
}
更新した投稿が分かっているなら、全削除の代わりに clean_post_cache( $post_id ) で対象だけ消すほうが、キャッシュの効きを落としません。
永続オブジェクトキャッシュを使っている環境では、transient も DB ではなくキャッシュに保存されます。wp_cache_flush() を呼ぶと transient も消えるので、処理結果などを transient に入れているなら、消す前に退避して、消した後に保存し直します。
if ( wp_using_ext_object_cache() ) {
$report = get_transient( 'my_report' );
wp_cache_flush();
if ( false !== $report ) {
set_transient( 'my_report', $report, DAY_IN_SECONDS );
}
}
まとめ
- APCu の永続オブジェクトキャッシュは、APCu Manager を入れて設定画面で有効にすれば使える
- 一括置換プラグインや phpMyAdmin で DB を直接書き換えたら、キャッシュを全削除する
- 編集画面に古い内容が出ていたら、、キャッシュを全削除する
- APCu は WP-CLI では消せない。管理バーのボタンか、Web 経由の
wp_cache_flush()で消す