WordPress:プラグインなしの人気記事もキャッシュする

WordPress:プラグインなしの人気記事もキャッシュする

相変わらず、別サイト「そんなには褒めないよ。映画評」の調整で、なかなか当サイトを自作テーマに変更できません(涙)。そろそろ完成にしないといけないのですが、今回は人気記事(よく読まれている記事)を前記事と同様に Transients API を使ってキャッシュしようということです。

01プラグインなし人気記事(よく読まれている記事)

WordPress でアクセス数の多い記事を表示するプラグインは WordPress Popular Posts がよく知られています。極力プラグインを使わずにおこうということもありますし、実際、必要としている機能は単純かつ一定ですので、自分で作ってしまえということで自作コードでまかなっています。

コードは上の記事にあります。全く問題なく稼働しています。

どのように実現しているかですが、まずアクセスデータ保存は、

  • 記事 ID 、時間を保存できる独自テーブルを2つ作成する
  • 投稿ページにアクセスがあれば、その2つのテーブルに記事 ID と現在時刻を保存する

と、テーブル2つにアクセスデータを保存します。ひとつは集計期間を変更することもありますのでバックアップ用です。

次にアクセスデータの集計、表示は、

  • 人気記事の表示ブロックから表示関数を呼び出す
  • 表示用テーブルのデータから指定期間外のデータを削除する
  • データーを記事 id ごとに集計し降順でソートし出力する
  • 表示ブロックで表示する

という流れになっています。

02負荷軽減のため Transients API を使ってキャッシュする

で、これですと投稿ページにアクセスがあるたびにデータベースを呼び出すことになりかなりの負荷がかかります。ですので、これも前記事と同じように Transients API を使ってキャッシュしようと思います。

ただ問題は、人気記事(よく読まれている記事)はアクセスがあるたびに変化するものですのでキャッシュの持続時間をそんなに長くはできませんので一定時間で更新する必要があります。

そのためには、WordPress が提供している定期実行の仕組み WP-Cron とサーバーの cron を使います。

WordPress の WP-Cron はサイトへのアクセスによって起動する仕組みですのでアクセスがなければ働きません。ですので、更新のスケジュールは WP-Cron に登録しますが、それを稼働させるのはサーバーの cron で行うということです。

WP-Cron については次のリンク先がわかりやすいです。英語ですが Google翻訳で十分理解できます。

03カスタムスケジュールの作成

デフォルトでは次の4つのスケジュールが登録されています。

  • 毎時(hourly)
  • 1日2回(twicedaily)
  • 毎日(daily)
  • 毎週 (weekly)WP 5.4 以降

今回は10分ごとに更新しようと思いますので10分ごとのカスタムスケジュールを作成します。リンク先にサンプルコードがあります。

function add_cron_10min( $schedules ) { 
    $schedules['10min'] = array(
        'interval' => 10*60,
        'display'  => esc_html__( 'Once Every Ten Minutes' ), );
    return $schedules;
}
add_filter( 'cron_schedules', 'add_cron_10min' );

04WP-Cron イベントの登録

WP-Cron イベントの登録は、

  • 独自のカスタムフックの作成
  • 実行する関数の作成
  • フックを WP-Cron イベントとして登録

という流れになります。

function imz_cron_pp_cache() {
    // よく読まれている記事キャッシュ
    $pp = new ImzPopularPosts( '1 DAY' );
    $ids = $pp->get_imz_popularposts(20); // 0 はすべて、デフォルトは 5
    if(!empty($ids)){
        $transient_name = 'popular_post_list';
        $query = new WP_Query(
            array(
                'post_status' => 'publish',
                'post__in' => $ids,
                'orderby' => 'post__in',
            )
        );
        set_transient( $transient_name, $query, 0 );
    }
}
add_action ( 'imz_cron_hook', 'imz_cron_pp_cache' );

フック名は独自のもので、確認しやすいようにプレフィックスを付けたほうがいいです。実行している関数は、表示したい人気記事の期間(上のコードでは1日)を指定してインスタンスを作成し、キャッシュしておく記事数(上のコードでは20件)を指定して呼び出し関数を呼びます。そして、データがあれば、Transients API を使ってデータベースに保存しておきます。

WP-Cron イベントとして登録

作成した独自フックを登録する関数は、wp_schedule_event() です。ただし、二重登録を避けるために wp_next_scheduled() を使って事前に確認する必要があります。次のようになります。

if ( ! wp_next_scheduled( 'imz_cron_hook' ) ) {
  wp_schedule_event( time(), '10min', 'imz_cron_hook' );
}

05WP-Cron の停止とサーバーの cron への登録

ということで、10分毎に人気記事をキャッシュする段取りはつきましたが、これですとアクセスがないと想定通りには稼働しません。また、WP-Cron そのものもアクセス時にかならず起動しますので不必要な負荷がかかります。

ですので、WP-Cron を停止し、その起動プログラムである wp-cron.php をサーバーの cron で定期実行するようにします。

WP-Cron の停止

WP-Cron を停止するにはドメイン直下のファイル wp-config.php の /* That's all, stop editing! Happy publishing. */ の前に次の一行を追加します。

define( 'DISABLE_WP_CRON', true );

サーバーの cron への登録

どのレンタルサーバーでも cron は使えると思います。

Xserver の場合です。

コマンドパスも実行するファイルもフルパスで指定します。

/usr/bin/php7.4 /home/xs******/movieimpressions.com/public_html/wp-cron.php 

以上で、10分毎に人気記事(よく読まれている記事)が Transients API を使ってキャッシュされます。

データベースの wp_options テーブルに新規記事、おすすめ記事とともに人気記事(よく読まれている記事)20件が10分毎のキャッシュされています。

なお、前回よくわからなかった autoload は、yes であればアクセス時に自動で読み込まれるようです。ですので、フロントページと投稿ページではかならず表示されるものですので全てキャッシュの保存を無期限にして autoload は yes にしています。

以上です。