カテゴリー
ブログ

定期/定時処理

定期処理

仮に「最近読まれているリスト」を1時間ごとに更新するとする。通常は次のように transient の寿命を1時間としておけばよい。

function lf_get_poplists() {
    if ( ! $lists = get_transient( 'LF_POPLISTS' ) {

        // リスト取得処理
        $lists = ...

        set_transient( 'LF_POPLISTS', $lists, HOUR_IN_SECONDS );
    }
    return $lists;
}

この更新を、ユーザーアクセスに依存せず定期的に実行するようにしてみた。上記のリスト取得処理部分を lf_set_poplists() という関数に切り出したうえで、1時間おきに実行するためにスケジュール登録する。

// フック名+引数がキーとなるので array()も明示しておく
if( ! wp_next_scheduled( 'lf_event_poplists', array() ) ) {
    // 第5引数を true にするために第4引数に array() を設定している
    if( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event_poplists', array(), true ) ) {
        // エラー処理
    }
}

// スケジュール登録したフックとアクションを関連づける
add_action('lf_event_poplists', 'lf_set_poplists', 10, 0);

// アクションの実行
function lf_set_poplists() {

    // リスト取得処理
    $lists = ...

    set_transient( 'LF_POPLISTS', $lists );
}
  • wp_schedule_event() がエラー時に WP_Error オブジェクトを返すようにするためには、第5引数を true にしなければならない(デフォルトは false)。となると第4引数も何かをセットしなければならず、デフォルト値の array() をセット。イベントを識別するキーはフックと引数なので、wp_next_scheduled() にも敢えて array() をセットした。
  • フック(上の例では ‘lf_event_poplists’)というものは、対応する do_action( ‘lf_event_poplists’ ) が必要なのだと思っていた。しかしスケジューラー内にフックを起動する機構があるので不要。
  • アクションに渡す引数は array() にくるむ必要がある。以下はサンプル。
// 引数あり(引数の数が決まっている場合)
if ( ! wp_next_scheduled( 'lf_event', array( 'a', 'b' ) ) ) {
    if ( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event', array( 'a', 'b' ), true ) ) {
        // エラー処理
    }
}
add_action( 'lf_event', 'lf_action', 10, 2 );
function lf_action( $arg1, $arg2) {
}

// 引数あり(引数の数が決められない場合)
if ( ! wp_next_scheduled( 'lf_event', array( array( 'a', 'b' ) ) ) ) {
    if ( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event', array( array( 'a','b ') ), true ) ) {
        // エラー処理
    }
}
add_action( 'lf_event', 'lf_action', 10, 1 );
function lf_action( $arg ) {
}

定時処理

LOTD(今日のリスト)を入れ替えるプログラムは毎日0:01に走らせている。現在はサーバーの cron から起動しているが、これを WordPress のスケジュールシステムに乗せるためには次のようにして起動時刻を指定する必要がある(実際に起動するのは、この指定時刻以降に wp_cron() が起動された時刻になる)。

$etime = new DateTimeImmutable( 'tomorrow 0:01', wp_timezone() );
if ( ! wp_next_scheduled( 'lf_event', array() ) ) {
    if ( ! $ret = wp_schedule_event( $etime->getTimeStamp(), 'daily', 'lf_event', array(), true ) ) {
    }
}

コメントを残す