2026年5月20日
2026年5月20日
WP-Cronをプラグインで使う方法|定期処理の登録・解除・WP-CLIでの確認とサーバーcron
WP-Cron は、WordPress に組み込まれている予約実行の仕組みです。サーバーの cron とは違い、サイトにアクセスがあったときに「実行時刻を過ぎた予約」があるかを調べ、あれば裏側で wp-cron.php を呼び出して処理します。メールの一括送信、古いデータの削除、外部 API からの取り込みなどをプラグインから定期的に動かすときに使います。この記事の関数とコマンドは、2026年11月時点で developer.wordpress.org の関数リファレンスと WP-CLI のコマンドリファレンスで確認したものです。
WP-Cron の仕組みと注意点
- 実行のきっかけはページへのアクセスです。アクセスが無い時間帯は、予定の時刻を過ぎても実行されません。
- 予約は「フック名」で管理されます。予約の時刻になると、そのフック名で
do_action()が呼ばれ、add_action()で登録した関数が動きます。 - 予約の情報はデータベースの
wp_optionsテーブル(cronという名前のオプション)に保存されます。プラグインを無効にしても予約は残るので、自分で消します。
定期処理を登録する
プラグインのメインファイルに書く例です。有効化したときに毎日の予約を作り、無効化したときに消します。
<?php
/**
* Plugin Name: My Cron Example
*/
// 1. 予約の時刻に動く処理をフックに結び付ける(毎回読み込まれる場所に書く)
add_action( 'myplugin_daily_task', 'myplugin_run_daily_task' );
function myplugin_run_daily_task() {
global $wpdb;
// 例: 30日より前のログを独自テーブルから削除する(created_at は UTC で保存している前提)
$table = $wpdb->prefix . 'myplugin_logs';
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$table} WHERE created_at < %s",
gmdate( 'Y-m-d H:i:s', time() - 30 * DAY_IN_SECONDS )
)
);
}
// 2. 有効化したときに予約を作る
register_activation_hook( __FILE__, 'myplugin_activate' );
function myplugin_activate() {
if ( ! wp_next_scheduled( 'myplugin_daily_task' ) ) {
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'myplugin_daily_task' );
}
}
// 3. 無効化したときに予約を消す
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );
function myplugin_deactivate() {
wp_clear_scheduled_hook( 'myplugin_daily_task' );
}
ポイントは次のとおりです。
add_action()は有効化の処理の中ではなく、ファイルの中で毎回実行される場所に書きます。予約だけあって処理が結び付いていないと、時刻になっても何も起きません。wp_schedule_event( 最初の実行時刻, 間隔, フック名 )の最初の引数は UNIX タイムスタンプ(UTC)です。WordPress に最初から用意されている間隔はhourly(1時間)、twicedaily(12時間)、daily(1日)、weekly(1週間、WordPress 5.4 から)の4つです。- 同じ予約を何度も作らないように、
wp_next_scheduled()で予約があるかを確かめてから登録します。 - 無効化のときは
wp_clear_scheduled_hook()を使うと、そのフック名(と引数)の予約をまとめて消せます。wp_unschedule_event()を使う場合は、wp_next_scheduled()で時刻を取ってから渡します。
独自の実行間隔を追加する
5分ごと・15分ごとなど、用意されていない間隔は cron_schedules フィルターで追加します。weekly はすでに WordPress にあるので、追加する必要はありません。
<?php
add_filter( 'cron_schedules', function ( $schedules ) {
$schedules['myplugin_every_15_minutes'] = array(
'interval' => 15 * MINUTE_IN_SECONDS,
'display' => '15分ごと',
);
return $schedules;
} );
register_activation_hook( __FILE__, function () {
if ( ! wp_next_scheduled( 'myplugin_sync_task' ) ) {
wp_schedule_event( time(), 'myplugin_every_15_minutes', 'myplugin_sync_task' );
}
} );
cron_schedules のフィルターは、予約を作るときにも、予約が実行されるときにも読み込まれている必要があります。プラグインのファイルの最上位(関数の外)に書いてください。間隔の名前は、他のプラグインとぶつからないように接頭辞を付けると安全です。
なお、WP-Cron はアクセスがきっかけで動くため、5分ごとの予約を作っても、5分ごとに実行されるとは限りません。間隔どおりに動かしたい場合は、後で説明するサーバーの cron と組み合わせます。
1回だけ実行する予約
投稿の公開時に重い処理を後回しにしたい、といった場合は wp_schedule_single_event() を使います。
<?php
// 投稿が公開されたら、1分後に後処理を予約する
add_action( 'publish_post', function ( $post_id ) {
wp_schedule_single_event( time() + MINUTE_IN_SECONDS, 'myplugin_process_post', array( $post_id ) );
} );
// 予約の時刻に動く処理。引数は予約のときに渡した配列の順に届く
add_action( 'myplugin_process_post', function ( $post_id ) {
$post = get_post( $post_id );
if ( ! $post ) {
return;
}
// ここに重い処理を書く(画像の加工、外部 API への送信など)
update_post_meta( $post_id, '_myplugin_processed', gmdate( 'c' ) );
} );
wp_schedule_single_event() には、同じフック名・同じ引数の予約がすでに10分以内にある場合、新しい予約を作らない仕様があります。引数に投稿 ID を入れておけば、投稿ごとに別の予約として扱われます。
WP-CLI で確認・実行する
WP-CLI が使えるサーバーでは、予約の状態を次のコマンドで確認できます。
# 予約の一覧(フック名・次の実行時刻・間隔)
wp cron event list --fields=hook,next_run_relative,recurrence
# 登録されている実行間隔の一覧(cron_schedules で追加したものも出る)
wp cron schedule list
# 指定したフックの予約を、今すぐ実行する
wp cron event run myplugin_daily_task
# 実行時刻を過ぎている予約をすべて実行する
wp cron event run --due-now
# 指定したフックの予約をすべて削除する
wp cron event delete myplugin_daily_task
# 試しに予約を作る(今から、毎日)
wp cron event schedule myplugin_daily_task now daily
# WP-Cron の呼び出し(ループバック)が動くかを確かめる
wp cron test
wp cron test が失敗する場合は、サーバーが自分自身の URL に接続できない(ファイアウォール、Basic 認証、DNS の設定など)可能性があります。管理画面の「ツール → サイトヘルス」でも、予約の遅れやループバック接続の問題が表示されます。
アクセスが少ないサイトではサーバーの cron から動かす
アクセスが少ないサイトや、決まった時刻に動かしたい処理がある場合は、アクセスをきっかけにした実行を止め、サーバーの cron から定期的に呼び出します。
まず wp-config.php の「編集が必要なのはここまでです」の行より上に、次の1行を追加します。
define( 'DISABLE_WP_CRON', true );
次に、サーバーの cron(crontab -e やレンタルサーバーの管理画面の cron 設定)に、次のどちらかを登録します。例は5分ごとです。
# WP-CLI を使う方法(パスはサーバーに合わせる)
*/5 * * * * cd /var/www/html && /usr/local/bin/wp cron event run --due-now --quiet
# HTTP で wp-cron.php を呼び出す方法
*/5 * * * * wget -q --delete-after "https://example.com/wp-cron.php?doing_wp_cron"
WP-CLI を使う方法は、Web サーバーのタイムアウトの影響を受けません。cron を実行するユーザーは、WordPress のファイルの所有者と同じユーザーにしておくと、ファイルの権限で失敗しにくくなります。DISABLE_WP_CRON を入れたのに cron の登録を忘れると、予約がまったく実行されなくなるので、wp cron event list で次の実行時刻が進んでいるかを確認してください。サーバー側の設定の詳細は「WordPressのWP-Cronをサーバーのcronで動かす設定」でも説明しています。
注意点
- 定期処理は、途中で止まっても次の回でやり直せるように作ります。WP-Cron は実行の失敗を通知しないので、必要なら処理の中でログを残します。
- 1回の処理に時間がかかる場合は、件数を区切って少しずつ処理します。PHP の実行時間の上限に引っかかると、途中で止まります。
- 管理画面ではプラグインを無効化してからでないと削除できないので、無効化のフックで予約を消しておけば、削除後にデータベースに予約が残りません。