2026年5月17日

2026年5月17日

WordPressのキャッシュエラーを解決する方法

はじめに

WordPressでページを更新したのにキャッシュが残っていて古いコンテンツが表示され続ける・キャッシュプラグインを導入したら管理画面にログインできなくなった・Object CacheにRedisを設定したが接続エラーで動かない・delete_transient()でTransientを削除したはずなのにデータが残っているといった問題は、WordPressのキャッシュシステムの仕組みと正しいキャッシュ制御を理解することで解決できます。

症状・原因

  • キャッシュプラグインがログインページやWordPress管理画面(/wp-admin/)もキャッシュしているため管理できなくなる
  • set_transient()で保存したデータが期限前に消える(Object Cacheのメモリ不足やEviction)
  • ページキャッシュのパージが投稿更新時に実行されず、古いキャッシュが残り続ける
  • Redisなどの外部Object Cacheで接続が切れるとwp-content/object-cache.phpがエラーを出す

解決手順

ステップ1:キャッシュエラーを診断する

# Object Cache の状態を確認
wp eval "
echo 'Object Cache: ' . (wp_using_ext_object_cache() ? '外部キャッシュ使用中' : 'デフォルト(非永続)') . PHP_EOL;
echo 'object-cache.php: ' . (file_exists(WP_CONTENT_DIR . '/object-cache.php') ? '✓ あり' : '× なし') . PHP_EOL;
"

# Transient の一覧を確認
wp eval "
global \$wpdb;
\$transients = \$wpdb->get_results(
    \"SELECT option_name, option_value FROM {\$wpdb->options}
     WHERE option_name LIKE '_transient_%' AND option_name NOT LIKE '_transient_timeout_%'
     LIMIT 20\"
);
foreach (\$transients as \$t) {
    echo \$t->option_name . PHP_EOL;
}
echo '合計: ' . count(\$transients) . ' 件';
"

# 期限切れ Transient を削除
wp eval "
global \$wpdb;
\$deleted = \$wpdb->query(
    \"DELETE FROM {\$wpdb->options} WHERE option_name LIKE '_transient_timeout_%'
     AND option_value < \" . time()
);
echo '期限切れ Transient を ' . \$deleted . ' 件削除';
"

# ページキャッシュプラグインの状態確認
wp plugin list --status=active | grep -i cache

ステップ2:WordPress Object Cacheを正しく使う

// ✅ WordPress Object Cache の正しい使い方
// wp_cache_set/get はリクエスト単位の非永続キャッシュ(デフォルト)
// Redis/Memcached を使うと永続化できる

// ✅ キャッシュグループとキーを適切に設計
function my_get_popular_posts(int $count = 5): array {
    $cache_key   = 'popular_posts_' . $count;
    $cache_group = 'my_plugin';

    // ✅ まずキャッシュを確認
    $cached = wp_cache_get($cache_key, $cache_group);
    if ($cached !== false) {
        return $cached;
    }

    // キャッシュミス: DBクエリを実行
    $posts = get_posts([
        'posts_per_page' => $count,
        'meta_key'       => 'post_views_count',
        'orderby'        => 'meta_value_num',
        'order'          => 'DESC',
    ]);

    // ✅ キャッシュに保存(1時間)
    wp_cache_set($cache_key, $posts, $cache_group, HOUR_IN_SECONDS);

    return $posts;
}

// ✅ 投稿更新時にキャッシュを削除
add_action('save_post', function(int $post_id): void {
    wp_cache_delete('popular_posts_5', 'my_plugin');
    wp_cache_delete('popular_posts_10', 'my_plugin');

    // グループ全体を削除(Redis 使用時)
    wp_cache_flush_group('my_plugin');
});

ステップ3:Transientキャッシュを正しく管理する

// ✅ Transient の正しい使い方(DB に保存される永続キャッシュ)
function my_get_api_data(string $endpoint): mixed {
    // ✅ キーは64文字以内にする(超えると保存されない)
    $cache_key = 'api_' . md5($endpoint);  // md5 で64文字以内に収める

    $cached = get_transient($cache_key);
    if ($cached !== false) {
        return $cached;   // ✅ false チェック(0 や空配列はキャッシュされている)
    }

    $response = wp_remote_get($endpoint);
    if (is_wp_error($response)) {
        // ✅ エラー時は短時間キャッシュ(再試行を許可)
        set_transient($cache_key, [], 5 * MINUTE_IN_SECONDS);
        return [];
    }

    $data = json_decode(wp_remote_retrieve_body($response), true) ?? [];

    // ✅ 有効期限を必ず指定(0 にすると期限なしになる)
    set_transient($cache_key, $data, 6 * HOUR_IN_SECONDS);

    return $data;
}

// ✅ バージョンを使ったグループ無効化
function my_get_cache_version(): int {
    return (int) get_option('my_plugin_cache_version', 1);
}

function my_invalidate_cache(): void {
    // バージョンをインクリメントするだけで全キャッシュが無効化される
    update_option('my_plugin_cache_version', my_get_cache_version() + 1);
}

function my_get_data_with_version(string $key): mixed {
    $versioned_key = $key . '_v' . my_get_cache_version();
    $versioned_key = substr($versioned_key, 0, 64); // 64文字制限
    return get_transient($versioned_key);
}

ステップ4:ページキャッシュの制御と除外設定

// ✅ キャッシュプラグインにキャッシュしないよう通知する(標準的な方法)
// ログイン中ユーザーのページをキャッシュしない
define('DONOTCACHEPAGE', true);     // WP Super Cache
define('DONOTCACHEDB', true);       // データベースキャッシュを無効化
define('DONOTMINIFY', true);        // 最小化を無効化

// ✅ 特定ページでキャッシュを無効化(functions.php)
add_action('template_redirect', function(): void {
    // カートページ・マイアカウントページはキャッシュしない
    if (function_exists('is_cart') && (is_cart() || is_checkout() || is_account_page())) {
        define('DONOTCACHEPAGE', true);

        // Cache-Control ヘッダーでブラウザキャッシュも無効化
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('Pragma: no-cache');
        header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
    }
});

// ✅ 投稿更新時にページキャッシュをパージ
add_action('save_post', function(int $post_id, WP_Post $post): void {
    if ($post->post_status !== 'publish') {
        return;
    }

    // WP Super Cache のパージ
    if (function_exists('wp_cache_post_change')) {
        wp_cache_post_change($post_id);
    }

    // W3 Total Cache のパージ
    if (function_exists('w3tc_pgcache_flush_post')) {
        w3tc_pgcache_flush_post($post_id);
    }

    // WP Rocket のパージ
    if (function_exists('rocket_clean_post')) {
        rocket_clean_post($post_id);
    }
}, 10, 2);

ステップ5:Redis/Memcachedの接続エラーを解決する

# Redis 接続テスト
wp eval "
if (class_exists('Redis')) {
    try {
        \$redis = new Redis();
        \$redis->connect('127.0.0.1', 6379, 1.0);
        echo 'Redis 接続: ✓' . PHP_EOL;
        echo 'Ping: ' . \$redis->ping() . PHP_EOL;
    } catch (Exception \$e) {
        echo 'Redis 接続エラー: ' . \$e->getMessage();
    }
} else {
    echo 'Redis 拡張: × インストールされていない';
}
"

# Object Cache をフラッシュ
wp cache flush

# Transient を全削除(緊急時)
wp eval "
global \$wpdb;
\$wpdb->query(\"DELETE FROM {\$wpdb->options} WHERE option_name LIKE '_transient_%'\");
echo 'Transient を全削除しました';
"
// ✅ wp-config.php に Redis 設定を追加
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
define('WP_REDIS_DATABASE', 0);
// ✅ Redis が落ちてもサイトが動くようにフォールバックを有効化
define('WP_REDIS_GRACEFUL', true);
define('WP_REDIS_MAXTTL', 86400); // 最大24時間

注意事項

  • キャッシュプラグインの除外設定で必ず/wp-admin//wp-login.php・Cookieベースのユーザー判定(wordpress_logged_in_*)を除外してください。除外しないと管理画面にアクセスできなくなります
  • set_transient()の有効期限(第3引数)に0を渡すと期限なし(永続)になります。外部Object Cacheを使用している場合はメモリ圧迫の原因になるため、必ず有効期限を指定してください

まとめ

WordPressのキャッシュエラーの解決は①wp_using_ext_object_cache()でObject Cache確認・Transient一覧と期限切れ削除・キャッシュプラグイン有効確認、②wp_cache_get/setでリクエストキャッシュ・save_postフックでwp_cache_deletewp_cache_flush_groupでグループ無効化、③Transientキーはmd5()で64文字以内・falseと比較して0や空配列もキャッシュ・バージョン番号でグループ一括無効化、④DONOTCACHEPAGE定数でページキャッシュ除外・WooCommerceカートページにCache-Control: no-storesave_postフックで各プラグインのパージ関数を呼出し、⑤wp cache flush・Redis接続テスト・WP_REDIS_GRACEFULでフォールバック設定・緊急時はTransient全削除の手順で解決します。

お気軽にご相談ください

お見積りへ お問い合わせへ