wp_next_scheduled():予約した定期処理の次に動く時刻を調べる(WordPress)

WordPress

wp_next_scheduled() は、WP-Cron(WordPress の予約した処理を動かす仕組み)に予約した処理が、次に動く時刻を調べる関数です。予約がなければ false が返るので、wp_schedule_event() と組み合わせて、同じ処理を二重に予約しないようにするのによく使います。

書き方

wp_next_scheduled( string $hook, array $args = array() ): int|false
  • $hook:予約したときのフック(アクション)の名前
  • $args:予約したときに渡した引数。予約したときと同じ配列を渡す
  • 戻り値:次に動く時刻の UNIX 時刻(1970 年 1 月 1 日からの秒数)。予約がなければ false

使い方の例

作業環境(WordPress 7.1.3)で試した結果を、コメントに書いています。試したあと、予約した処理は wp_clear_scheduled_hook() で消し、wp_next_scheduled() が false に戻ったことを確認しています。

二重に予約しないように登録する

いちばんよく使う形です。init のたびに予約があるかを確認し、なければ予約します。作業環境で、この関数を続けて 2 回呼んでも、予約は 1 つだけでした。

functions.php
<?php
// 1 日 1 回動かす処理を、二重に予約しないように登録する
add_action( 'init', 'my_schedule_daily_task' );
function my_schedule_daily_task() {
	if ( ! wp_next_scheduled( 'my_daily_task' ) ) {
		wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'my_daily_task' );
	}
}

add_action( 'my_daily_task', 'my_run_daily_task' );
function my_run_daily_task() {
	// 1 日 1 回する処理
}

次に動く時刻を調べる

<?php
var_dump( wp_next_scheduled( 'my_daily_task' ) ); // bool(false)(まだ予約していない)

wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'my_daily_task' );

$ts = wp_next_scheduled( 'my_daily_task' );
echo $ts;                                     // 1793082151(UNIX 時刻)
echo wp_date( 'Y-m-d H:i:s', $ts );           // サイトのタイムゾーン(Asia/Tokyo)の日時で表示
echo wp_get_schedule( 'my_daily_task' );      // daily(間隔の名前)

確認せずに予約すると重なる

wp_next_scheduled() で確認せずに wp_schedule_event() を呼ぶと、時刻が違えば同じ処理がいくつでも予約されます。ページを開くたびに予約していると、気づかないうちに同じ処理が何度も動きます。

<?php
// 確認せずに続けて予約すると、時刻が違えばいくつでも予約される
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'my_daily_task' );     // true
wp_schedule_event( time() + 2 * HOUR_IN_SECONDS, 'daily', 'my_daily_task' ); // true
wp_schedule_event( time() + 2 * DAY_IN_SECONDS, 'daily', 'my_daily_task' );  // true
// → my_daily_task が 3 つ予約され、1 日に 3 回動く

echo wp_clear_scheduled_hook( 'my_daily_task' ); // 3(消した数)

$args も同じでないと見つからない

WP-Cron は、フックの名前と $args の組み合わせで予約を見分けます。$args を付けて予約したものは、同じ $args を渡さないと見つかりません。

<?php
// $args を付けて予約したものは、同じ $args で探さないと見つからない
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'my_daily_task' );
wp_schedule_event( time() + 2 * HOUR_IN_SECONDS, 'hourly', 'my_daily_task', array( 'post_type' => 'my_article' ) );

echo wp_next_scheduled( 'my_daily_task' );                                      // 1 つ目の時刻($args なしのもの)
echo wp_next_scheduled( 'my_daily_task', array( 'post_type' => 'my_article' ) ); // 2 つ目の時刻
var_dump( wp_next_scheduled( 'my_daily_task', array( 'post_type' => 'post' ) ) ); // bool(false)

// 消すときも $args ごとに
echo wp_clear_scheduled_hook( 'my_daily_task' );                                      // 1
echo wp_clear_scheduled_hook( 'my_daily_task', array( 'post_type' => 'my_article' ) ); // 1

プラグインを止めるときに予約を消す

予約は、プラグインやテーマを止めてもデータベースに残ります。止めるときに消しておくと、動かない予約が残り続けません。

<?php
// プラグインを止めるときは、予約も消す(メインのファイルに書く)
register_deactivation_hook( __FILE__, 'my_unschedule_daily_task' );
function my_unschedule_daily_task() {
	wp_clear_scheduled_hook( 'my_daily_task' );
}

予約投稿の公開の予定を調べる

ここからの 2 つの節では、WP-Cron に入っている処理を「予定」と呼びます(上の節の「予約」と同じものです)。予約投稿を保存すると、WordPress は publish_future_post というフックの予定を 1 つ登録します。$args は投稿の ID が 1 つだけ入った配列です。そのため、array( 投稿の ID ) を渡すと、その投稿が公開される予定の時刻が分かります。

<?php
// 予約投稿(ID は 123 とする)の公開の予定を調べる
$ts = wp_next_scheduled( 'publish_future_post', array( 123 ) );
echo $ts;                             // 1793941599(UNIX 時刻)
echo wp_date( 'Y-m-d H:i:s', $ts );   // 2026-11-06 14:06:39(投稿の日時と同じ)

// ID を文字で渡すと見つからない
var_dump( wp_next_scheduled( 'publish_future_post', array( '123' ) ) ); // bool(false)

// $args を省いても見つからない
var_dump( wp_next_scheduled( 'publish_future_post' ) ); // bool(false)

作業環境で試すと、予定の時刻は、投稿の post_date_gmt を UNIX 時刻にしたものと同じでした。公開されると予定は消え、false が返ります。

予約投稿と予定を並べて見る

予約投稿が「予約済み」のまま残っているときに、予定があるのに動いていないのか、予定そのものがないのかを分けて見る例です。

<?php
// 予約済みの投稿ごとに、公開の予定と、時刻を過ぎているかを出す
$posts = get_posts( array(
	'post_status' => 'future',
	'numberposts' => -1,
	'orderby'     => 'date',
	'order'       => 'ASC',
) );
foreach ( $posts as $post ) {
	$ts   = wp_next_scheduled( 'publish_future_post', array( $post->ID ) );
	$late = strtotime( $post->post_date_gmt . ' GMT' ) <= time();
	printf(
		"%d\t%s\t%s\t%s\n",
		$post->ID,
		$post->post_date,
		$ts ? wp_date( 'Y-m-d H:i', $ts ) : '予定なし',
		$late ? '時刻を過ぎている' : ''
	);
}

WP-Cron を止めている作業環境で動かすと、時刻を過ぎた予約投稿が、予定を持ったまま残っていました。この形なら、予定はあるので、WP-Cron が動いていないほうを疑います。「予定なし」と出る投稿は、予定が消えているので、投稿を保存し直すと予定が入り直ります。

気をつけること

  • WP-Cron は、だれかがサイトのページを開いたときに、時刻を過ぎた予約を動かします。時刻を過ぎても、ページが開かれるまでは動きません。アクセスの少ないサイトや、決まった時刻に動かしたい処理は、サーバーの cron(決まった時刻にコマンドを動かすサーバーの機能)から wp-cron.php を開くようにしてください。
  • wp-config.php で DISABLE_WP_CRON を true にしているサイトでは、ページを開いても予約は動きません。サーバーの cron から動かしているかを確認してください。
  • 戻り値は UNIX 時刻なので、日時で見るときは wp_date() を使うと、サイトのタイムゾーンで表示できます。
  • 同じフック・同じ $args・同じ時刻のものを続けて予約すると、2 つ目は false が返りました(作業環境で確認した結果)。時刻が違うと予約されるので、wp_next_scheduled() で確認する形にしておくのが確かです。
  • 予約の一覧を画面で見たいときは、WP-Cron の予約を一覧で表示するプラグインを使うと、フック・次の時刻・間隔をまとめて確認できます。
  • 予約投稿の予定(publish_future_post)は、$args が array( 投稿の ID ) です。ID は数字で渡します。array( '123' ) のように文字で渡すと、同じ投稿でも見つかりません(作業環境で確認した結果)。

関係する関数

逆引きリファレンスの一覧へ