WordPressで使える簡易なキャッシュ機能で、有効期限付きでデータをDB(wp_optionsテーブル)に一時保存できます。キャッシュの作成も破棄も簡単な関数で制御できます。WP_Queryで複雑な条件を指定して取得するような重めのデータや、ある程度の期間内容が変わらないようなWeb APIから取得するデータなどをキャッシュしておくと、アクセスするたびに発生するDBやAPIへのリクエストを減らすことができ、無駄なアクセスやサーバー負荷を抑えることが可能です。
Transients API
https://wpdocs.osdn.jp/Transients_API
特に内部的に自動で使えるようになっているわけではないので、使いたい場所でコードを書いて使います。
WordPressの関数として用意されているので使い方はとてもシンプルです。
<?php set_transient( $transient, $value, $expiration ); ?>
$transient
$value
$expiration
関数リファレンス/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 transient
、get_site_transient
、delete_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を使っておけば問題ありません。
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だと思います。
他の使い方を知りたい場合は、いろんなプラグインの中身を見てみると、けっこう使われていることが多いので参考になります。