MENU CLOSE

【WordPress】
Transients APIを使って
データをキャッシュする方法

Transients API
Transients API

Transients APIとは

WordPressで使える簡易なキャッシュ機能で、有効期限付きでデータをDB(wp_optionsテーブル)に一時保存できます。キャッシュの作成も破棄も簡単な関数で制御できます。WP_Queryで複雑な条件を指定して取得するような重めのデータや、ある程度の期間内容が変わらないようなWeb APIから取得するデータなどをキャッシュしておくと、アクセスするたびに発生するDBやAPIへのリクエストを減らすことができ、無駄なアクセスやサーバー負荷を抑えることが可能です。

Transients API

https://wpdocs.osdn.jp/Transients_API

Transients APIの使い方

特に内部的に自動で使えるようになっているわけではないので、使いたい場所でコードを書いて使います。
WordPressの関数として用意されているので使い方はとてもシンプルです。

キャッシュの作成

<?php set_transient( $transient, $value, $expiration ); ?>
  • $transient
    キャッシュの名前。長さ45 文字以下の制限あり。キャッシュを使う時、破棄する時に使います。
  • $value
    キャッシュするデータ。単純な文字列や数値はもちろん、配列やオブジェクトもキャッシュできます。
  • $expiration
    キャッシュが切れるまでの秒数。0は無期限。この期間を過ぎるとキャッシュは自動的に破棄されます。

関数リファレンス/set transient

https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/set_transient

キャッシュの取得

<?php get_transient( $transient ); ?>
  • $transient
    set_transientで指定したキャッシュの名前。

戻り値にキャッシュしたデータが返ってきます。
キャッシュが存在しないか、データがない、もしくは有効期限が切れている場合はfalseを返します。

<?php
//戻り値を変数に入れる
$transients = get_transient( 'transients_data' );

//空判定
if( !empty($transients) ){
  // キャッシュがある時の処理
}
?>

実際のコードではこんな感じで使うことになります。

関数リファレンス/get transient

https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/get_transient

キャッシュの削除

<?php delete_transient( $transient ); ?>
  • $transient
    set_transientで指定したキャッシュの名前。

関数リファレンス/delete transient

https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/delete_transient

また、ダッシュボードからボタン一つでTransientを全てクリアするプラグイン「Clear Transient From Dashboard」というものもあります。

とにかく全部一括で消して確認したいっていう場合にはこちらのプラグインがおすすめです。

その他の関数

set site transientget_site_transientdelete_site_transientというsite_がついた関数があります。似た様な名前の関数なのですが、同じのデータを扱えるわけではありません。これらはWordPressをマルチサイトとして使うときにネットワーク全体で共通で使えるようになるものです。

<?php 
//データをキャッシュ
set_transient( 'transient_data', 1, 60 * 60 * 24);
set_site_transient( 'transient_data', 2, 60 * 60 * 24);

//キャッシュを取得
get_transient( 'transient_data' ); // 1
get_site_transient( 'transient_data' ); // 2
?>

このようにsite_が付いているかついていないかで扱いが違ってきます。
マルチサイトはデメリットがあるので、かなり特殊な事情がないと選択しない手法ですし、その上サイトを跨いでキャッシュを使うことなんてまぁないです。

通常はsite_のついていないTransientを使っておけば問題ありません。

WP_Queryをキャッシュしてみる

Transients APIを使ってWP_Queryで取得したデータをキャッシュしてみます。

<?php
$transient_name = 'new_post_list';
$query = get_transient($transient_name); //もしキャッシュがあれば利用
if(empty($query)){
  $args = [
    'post_type'              => 'post',
    'posts_per_page'         => -1,
    'orderby'                => 'date'
  ];
  $query = new WP_Query( $args );
  //ログインユーザーはキャッシュしない
  if(!is_user_logged_in()){
    set_transient( $transient_name, $query, 60 * 60 * 24 );
  }
}

if ( !empty($query) && $query->have_posts() ):
  while ( $query->have_posts() ) :
    $query->the_post();

    //ループの内容

  endwhile;
  wp_reset_postdata();
endif;

このようにしておくと、ページを表示するたびにWP_Queryの引数によって内部的に実行していた複雑なSQLを省略して、キャッシュしたデータを扱うことができます。

ここではサンプルコードなので、新着記事10記事のキャッシュですが、meta_queryパラメータを使ってカスタムフィールドの値を条件にしたり、date_queryパラメータを使って日時を条件に加えたりとパラメータによって条件が複雑になることで負荷が増し、重くなることもあります。

そういった時に上記のコードのようにTransient APIでキャッシュしておくとかなりの負荷を削減できます。

記事の更新時にキャッシュを消す

上記でキャッシュはうまくいくのですが、このままでは有効期限の1日が経過するまでの間、ずっとキャッシュを参照してしまい、その間に記事を公開したり削除したりしても反映されません。

つまり記事の公開・更新・削除のタイミングでキャッシュのクリアが必要になります。
具体的には下記のようにアクションフックを利用してTransientを破棄します。

functions.php

function clear_transient_cache() {
  delete_transient('new_post_list');
}
add_action( 'publish_post', 'clear_transient_cache');
add_action( 'deleted_post', 'clear_transient_cache');
add_action( 'save_post', 'clear_transient_cache');
add_action( 'edit_post', 'clear_transient_cache');

こうしておくことで、記事の更新のタイミングでキャッシュが破棄され、次にページを表示した時は新しいキャッシュに置き換わります。

キャッシュを扱う時の注意点

なんでもかんでもWP_QueryをTransientでキャッシュすればええやん!って思う方がいるかもしれませんので、注意点を書いておきます。先ほどのコードを使って説明します。

<?php
$transient_name = 'new_post_list';
$query = get_transient($transient_name); //もしキャッシュがあれば利用
if(empty($query)){
  $args = [
    'post_type'              => 'post',
    'posts_per_page'         => -1,
    'orderby'                => 'date'
  ];
  $query = new WP_Query( $args );
  //ログインユーザーはキャッシュしない
  if(!is_user_logged_in()){
    set_transient( $transient_name, $query, 60 * 60 * 24 );
  }
}

if ( !empty($query) && $query->have_posts() ):
  while ( $query->have_posts() ) :
    $query->the_post();

    //ループの内容

  endwhile;
  wp_reset_postdata();
endif;

ここでTransientを使う際にはポイントがあります。
コメントにある通り、is_user_logged_in関数で条件判定し、WPにログインしているユーザーはキャッシュしないようにしておくことです。

理由は、例えば非公開記事として記事を書いて、その記事はログインユーザーだけが見れるようになっている場合、そのままキャッシュされてしまったらログインユーザー以外にも非公開記事が表示されてしまいます。それは非常にまずいですよね。

ここではログインユーザーはキャッシュの対象に含まないようにして防止しましたが、そもそもキャッシュを使うべきではないような場面もあります。

  • ログイン/ログアウトで内容が変わるデータ
  • ランダム表示のデータ
  • 現在時間と比較して表示するようなデータ

こういうものはキャッシュと相性が悪いので、キャッシュを使わない方が良いでしょう。
どうしても取り入れたい時は、本当に必要かどうか、キャッシュの作成と破棄がちゃんとできる設計になっているか、しっかり検討しましょう。

おわりに

今回はTransient APIについてメモしました。
WPですぐに使えるWP_Queryを例にしましたが、WP内であればどこでも使えるので、他にもカテゴリーやタグ一覧をキャッシュしたり、郵便番号や祝日のデータなど、WebAPIから引っ張ってきて何か処理する場合に、直接アクセスせずにREST APIを噛ませてWPにキャッシュしておいたものを処理したり、などなど使い方は様々です。

ただ、あくまで一時的なデータ保存として使うことを主目的とすることが大事です。そのためTransientとして扱うデータは、有効期限が切れたら再取得できるものに限ります。

そこさえ守れば、いろいろと使えて開発が捗る便利なAPIだと思います。
他の使い方を知りたい場合は、いろんなプラグインの中身を見てみると、けっこう使われていることが多いので参考になります。

記事一覧

RELATED

テキストの無限ループアニメーション【CSS + JS】
inoue
inoueのサムネイル
TIPS

【CSS + JS】テキストの無限ループアニメーション

shopify
inoue
inoueのサムネイル
TIPS

【Shopify】カートへの遷移を飛ばしてチェックアウトに進むボタンを設置する

PhotoSwipe v5
inoue
inoueのサムネイル
TIPS

【JS】PhotoSwipe v5を使って画像をポップアップ表示する

AVIF [ gulpでjpg・pngからAVIF画像を生成 ]
inoue
inoueのサムネイル
TIPS

gulpでjpg・pngからAVIF画像を生成する

MutationObserverでDOMを監視[PhotoSwipe(v5)+Swiper(v8)連携]
inoue
inoueのサムネイル
TIPS

【JS】MutationObserverでDOMを監視[PhotoSwipe(v5)+Swiper(v8)連携]

Google Sheets API スプレッドシートのデータをJSONで取得する
inoue
inoueのサムネイル
TIPS

【Google Sheets API】 スプレッドシートのデータをJSONで取得する

NEW POSTS

GA4連携人気記事ランキング機能を自作プラグイン化してみ【WordPress】
inoue
inoueのサムネイル
TRY

【WordPress】GA4連携の人気記事ランキング機能を自作プラグイン化してみた

netlify UPDATE BUILD IMAGE [ビルドイメージの更新]
inoue
inoueのサムネイル
TRY

【netlify】ビルドイメージを更新 [ Ubuntu Xenial 16.04 → Ubuntu Focal 20.04 ]

Google Business Profile API [ PHPでクチコミ一覧取得 ]
inoue
inoueのサムネイル
TIPS

【PHP】Google Business Profile APIを使ってクチコミを取得する

screendot screenshot API
inoue
inoueのサムネイル
TRY

スクリーンショットのAPI「screendot」を使ってみた

window.matchMedia hoverを判定
inoue
inoueのサムネイル
TIPS

【window.matchMedia】メディアクエリでhoverが使えるデバイスを判定

lax.js
inoue
inoueのサムネイル
TIPS

lax.jsの使い方【スクロール連動アニメーションの実装】

ブログ記事一覧
  • HOME
  • TIPS
  • 【WordPress】Transients APIを使ってデータをキャッシュする方法