1. ホーム
  2. WordPress

【WordPress】Transients API でデータをキャッシュする方法|set_transient / get_transient

Share

外部 API のレスポンスや重いデータベースクエリの結果を、毎回ゼロから取得していると、ページ表示が遅くなりがちです。WordPress には、こうした「一定時間だけ使い回したいデータ」を簡単にキャッシュできる Transients API が用意されています。この記事では set_transient() / get_transient() / delete_transient() の使い方を、引数の意味や定番の実装パターン、つまずきやすいポイントまで含めて初心者向けに解説します。

Transients API とは何か

Transients API は、有効期限付きでデータを一時保存するための仕組みです。「トランジェント(transient)」は「一時的な」という意味で、その名のとおり「ずっと残しておく必要はないけれど、毎回作り直すのは無駄」というデータを保存するのに向いています。

典型的な用途は、外部サービスの API から取得したデータや、集計のために何度も JOIN するような重いクエリの結果です。たとえば天気予報 API を毎回呼び出すとレスポンスが遅くなりますが、結果を1時間キャッシュしておけば、その間はキャッシュから瞬時に返せます。WordPress 標準の関数なので、追加のライブラリやプラグインは必要ありません。

基本の3つの関数

Transients API の中心となるのは、保存・取得・削除を担う次の3つの関数です。まずはそれぞれの役割を押さえておきましょう。

関数説明
set_transient( $key, $value, $expiration )キャッシュを保存する。第3引数で有効期限(秒)を指定する
get_transient( $key )キャッシュを取得する。存在しない、または期限切れのときは false を返す
delete_transient( $key )指定したキャッシュを削除する

保存する値($value)は文字列だけでなく、配列やオブジェクトも指定できます。WordPress が内部でシリアライズして保存し、取得時に元の形に戻してくれるためです。

set_transient() の引数

set_transient() の引数は次のとおりです。特に第3引数の $expiration は「秒」で指定する点を間違えやすいので注意してください。

引数説明
$keystringキャッシュを識別する名前。172文字以内が推奨される(接頭辞を付けて重複を避ける)
$valuemixed保存する値。文字列・配列・オブジェクトなどを指定できる
$expirationint有効期限をで指定する。0(既定値)を指定すると期限なし(自動では消えない)

戻り値は、保存に成功すれば true、失敗すれば false です。

有効期限は時間定数を使うと読みやすい

$expiration3600 のような秒数を直接書いてもよいのですが、それが何時間なのかは一目では分かりません。WordPress には時間を表す定数が用意されているので、これを使うとコードが読みやすくなります。

定数意味秒数
MINUTE_IN_SECONDS1分60
HOUR_IN_SECONDS1時間3600
DAY_IN_SECONDS1日86400
WEEK_IN_SECONDS1週間604800
MONTH_IN_SECONDS30日2592000
YEAR_IN_SECONDS365日31536000

たとえば「12時間キャッシュしたい」なら、12 * HOUR_IN_SECONDS のように掛け算で書けます。これなら後から読んでも意図がすぐに伝わります。

最小のコード例

まずは、値を保存して取り出すだけの最小の例です。1時間だけ有効なキャッシュを保存し、別のタイミングで取得しています。

functions.php
// キャッシュを保存する(有効期限は1時間)
set_transient( 'my_sample_data', 'こんにちは', HOUR_IN_SECONDS );

// キャッシュを取得する
$data = get_transient( 'my_sample_data' );

if ( false === $data ) {
    // 期限切れ、またはまだ保存されていない場合
    echo 'キャッシュはありません';
} else {
    echo $data; // こんにちは
}

ポイントは、取得結果が false かどうかで「キャッシュがあるか」を判定している点です。なぜ false で判定するのかは、このあとの定番パターンと注意点で詳しく説明します。

定番パターン:なければ作って保存する

Transients API でもっともよく使われるのが、「まずキャッシュを取得してみて、無ければ本来の処理でデータを作り、それを保存する」という流れです。2回目以降のアクセスではキャッシュが返るため、重い処理は最初の1回だけで済みます。

次の例は、外部 API からデータを取得してキャッシュする関数です。get_transient()false を返したときだけ実際に API を呼び出し、結果を12時間キャッシュしています。

functions.php
function my_get_external_data() {
    $cache_key = 'my_external_api_data';

    // 1. まずキャッシュを取得する
    $data = get_transient( $cache_key );

    // 2. キャッシュが無い、または期限切れなら再生成する
    if ( false === $data ) {
        $response = wp_remote_get( 'https://example.com/api/posts' );

        // 通信に失敗したら空配列を返す(失敗結果はキャッシュしない)
        if ( is_wp_error( $response ) ) {
            return array();
        }

        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );

        // 3. 取得したデータを12時間キャッシュする
        set_transient( $cache_key, $data, 12 * HOUR_IN_SECONDS );
    }

    return $data;
}

この関数を呼び出すだけで、12時間に1回しか外部 API へアクセスしなくなります。通信エラーのときはあえてキャッシュせず空配列を返しているので、一時的な障害が長時間キャッシュされてしまう事故を防げます。

get_transient() が false を返す意味と落とし穴

Transients API を使ううえで、もっとも理解しておきたいのが get_transient() の戻り値です。ここを誤解すると、意図しない動作の原因になります。

「無い」と「期限切れ」はどちらも false

get_transient() は、キャッシュが存在しないとき、または有効期限が切れているときに false を返します。つまり「キャッシュがまだ無い」場合と「あったが期限が切れた」場合を、戻り値だけでは区別できません。多くの場合はどちらも「再生成すればよい」ので、これで問題ありません。

保存した値が本当に false の場合は要注意

注意が必要なのは、保存したい値そのものが false になり得るケースです。たとえば「処理結果が成功なら true、失敗なら false」といった真偽値をそのままキャッシュすると、取得時に「値が false なのか、キャッシュが無いから false なのか」を区別できません。結果として、本来キャッシュされているのに毎回再生成されてしまいます。

対策としては、false をそのまま保存せず、配列でラップするか、0'no' といった別の値に置き換えて保存します。次の例では結果を配列に包んで保存しています。

functions.php
$cached = get_transient( 'my_flag_cache' );

if ( false === $cached ) {
    // 本来の処理。結果が false になることもある
    $result = my_check_something(); // true または false

    // false を直接保存すると区別できないので配列でラップする
    set_transient( 'my_flag_cache', array( 'value' => $result ), HOUR_IN_SECONDS );

    $value = $result;
} else {
    // ラップした配列から取り出す
    $value = $cached['value'];
}

このように一段かぶせておけば、配列が返ればキャッシュあり、false が返ればキャッシュ無し、と確実に判定できます。

有効期限はあくまで「最大」である

$expiration で指定した時間は、キャッシュが「最大でどれだけ生き残るか」を表すものです。指定した時間ぴったりに削除されるとは限りません。この挙動は、トランジェントがどこに保存されているかによって変わります。

永続オブジェクトキャッシュが無い場合

Redis や Memcached などの永続オブジェクトキャッシュを導入していない一般的な環境では、トランジェントは wp_options テーブルに保存されます。このとき、有効期限を過ぎたデータがその瞬間に自動で消えるわけではありません。期限切れの判定は、get_transient() でアクセスされたときに行われ、そこで初めて削除されます。つまり、誰もアクセスしなければ期限切れのデータがテーブルに残り続けることもあります(不要データの掃除自体は WordPress が定期的に行います)。

永続オブジェクトキャッシュがある場合

一方、永続オブジェクトキャッシュが有効な環境では、トランジェントはデータベースではなくそのキャッシュ機構に保存されます。この場合は wp_options には書き込まれず、期限切れの扱いもキャッシュ側に任されます。サーバーの再起動やキャッシュのクリアによって、有効期限より早くデータが消えることもあります。いずれにせよ、トランジェントは「いつ消えても困らない再生成可能なデータ」を入れるもの、と考えておくのが安全です。

キャッシュが更新されない・古いまま残るときの対処

「データを変更したのにサイトに反映されない」というときは、古いトランジェントが残っているのが原因のことがあります。状況別に対処を見ていきましょう。

更新時に明示的に削除する

元データが変わったタイミングで、delete_transient() を呼んでキャッシュを消すのが基本です。たとえば投稿が保存されたときにキャッシュを破棄しておけば、次回のアクセスで最新データが再生成されます。save_post などのフックに合わせて削除するとよいでしょう。

functions.php
// 投稿が保存されたらキャッシュを削除する
function my_clear_cache_on_save( $post_id ) {
    delete_transient( 'my_external_api_data' );
}
add_action( 'save_post', 'my_clear_cache_on_save' );

永続オブジェクトキャッシュが影響している場合

永続オブジェクトキャッシュを使っている環境では、データベースを直接見てもトランジェントが見つからないことがあります(前述のとおりキャッシュ側に保存されているためです)。wp_options を SQL で削除しても消えない場合は、オブジェクトキャッシュのクリアが必要です。delete_transient() を通して削除すれば、保存先がどこであっても正しく消えるので、データベースを直接操作するのではなく必ず関数経由で削除しましょう。

キーの付け方で取り違えていないか確認する

保存時と取得時で $key がわずかに違うと、当然キャッシュはヒットしません。タイプミスや、プラグイン・テーマ間でのキー重複が原因になることもあります。my_ のような独自の接頭辞を付けてキー名を一元管理しておくと、こうした取り違えを防ぎやすくなります。

まとめ

Transients API は、外部 API の結果や重いクエリを一定時間キャッシュして、サイトを高速化するための標準機能です。最後に要点を振り返っておきましょう。

  • set_transient($key, $value, $expiration) で保存、get_transient($key) で取得、delete_transient($key) で削除する。
  • $expiration は秒で指定し、HOUR_IN_SECONDS などの定数を使うと読みやすい。
  • get_transient() は「無い・期限切れ」のとき false を返すので、false 判定で再生成するのが定番パターン。
  • 値そのものが false になり得る場合は、配列でラップして保存する。
  • 有効期限は最大値であり、保存先(DB か永続オブジェクトキャッシュか)によって消えるタイミングが変わる。

「消えても再生成できるデータ」を入れる、という前提さえ守れば、Transients API は手軽で強力なキャッシュ手段になります。まずは重い処理を1つ、定番パターンでキャッシュしてみてください。

参考ページ