2026年7月11日
2026年7月11日
WordPressのwp_cronで定期処理を実装する方法
はじめに
「毎日深夜に古い一時データを削除したい」「1時間ごとに外部APIからデータを取得して更新したい」「定期的にサイトマップを再生成したい」——wp_cronを使えばWordPressで定期的なバックグラウンド処理を実装できます。
症状・原因
WordPressのwp_cronはリクエストベースで動作するため、サイトへのアクセスがないと発火しません。アクセスの少ないサイトではサーバーの実cronと組み合わせると確実に実行できます。また重複登録を防がないと、同じジョブが複数スケジュールされる問題が発生します。
解決手順
ステップ1:cronイベントを登録する
// functions.php: cronイベントをactivation時に登録
register_activation_hook( __FILE__, 'my_cron_activation' );
function my_cron_activation() {
if ( ! wp_next_scheduled( 'my_daily_cleanup' ) ) {
wp_schedule_event( time(), 'daily', 'my_daily_cleanup' );
}
}
// プラグイン無効化時にcronを削除
register_deactivation_hook( __FILE__, 'my_cron_deactivation' );
function my_cron_deactivation() {
$timestamp = wp_next_scheduled( 'my_daily_cleanup' );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, 'my_daily_cleanup' );
}
}
// テーマのfunctions.phpで使う場合(activation hookが使えないため)
add_action( 'init', function() {
if ( ! wp_next_scheduled( 'my_daily_cleanup' ) ) {
wp_schedule_event( time(), 'daily', 'my_daily_cleanup' );
}
} );
ステップ2:カスタムスケジュール間隔を追加する
// functions.php: WordPressのデフォルトにないスケジュール間隔を追加
add_filter( 'cron_schedules', function( $schedules ) {
// 5分ごと
$schedules['every_5_minutes'] = [
'interval' => 5 * MINUTE_IN_SECONDS,
'display' => '5分ごと',
];
// 30分ごと
$schedules['every_30_minutes'] = [
'interval' => 30 * MINUTE_IN_SECONDS,
'display' => '30分ごと',
];
// 週2回(月・木)はwp_cronの制限で正確には実装できないため
// 毎週でスケジュールして関数内で曜日チェック
return $schedules;
} );
// カスタム間隔でイベントを登録
add_action( 'init', function() {
if ( ! wp_next_scheduled( 'my_api_fetch' ) ) {
wp_schedule_event( time(), 'every_30_minutes', 'my_api_fetch' );
}
} );
ステップ3:cronフックに処理を実装する
// functions.php: 日次クリーンアップ処理
add_action( 'my_daily_cleanup', function() {
global $wpdb;
// 30日以上前の自動下書きを削除
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->posts}
WHERE post_status = 'auto-draft'
AND post_modified < %s",
gmdate( 'Y-m-d H:i:s', strtotime( '-30 days' ) )
)
);
// 期限切れトランジェントを削除
delete_expired_transients();
error_log( '[my_cron] daily_cleanup 実行完了: ' . gmdate( 'Y-m-d H:i:s' ) );
} );
// 外部APIからデータを取得してキャッシュに保存
add_action( 'my_api_fetch', function() {
$cache_key = 'my_api_data';
// APIリクエスト
$response = wp_remote_get( 'https://api.example.com/data', [
'timeout' => 15,
'headers' => [
'Authorization' => 'Bearer ' . get_option( 'my_api_key' ),
],
] );
if ( is_wp_error( $response ) ) {
error_log( '[my_cron] API取得エラー: ' . $response->get_error_message() );
return;
}
$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
error_log( '[my_cron] API HTTPエラー: ' . $code );
return;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( $body ) {
set_transient( $cache_key, $body, HOUR_IN_SECONDS );
error_log( '[my_cron] API取得完了: ' . gmdate( 'Y-m-d H:i:s' ) );
}
} );
ステップ4:サーバーcronと連携して確実に実行する
# /etc/cron.d/wordpress または crontab -e で設定
# DISABLE_WP_CRON を有効にしてサーバーcronで呼び出す
# 毎分WordPressのcronを実行(wp-cliを使用)
* * * * * www-data /usr/local/bin/wp cron event run --due-now --path=/var/www/html --quiet
# または wgetで直接叩く(wp-cliがない場合)
* * * * * www-data wget -q -O /dev/null https://example.com/wp-cron.php?doing_wp_cron
# wp-config.phpでWordPress側のcronを無効化
# define( 'DISABLE_WP_CRON', true );
// wp-config.php: サーバーcronを使う場合はWordPressの自動cronを無効化
define( 'DISABLE_WP_CRON', true );
// これによりページ読み込み時にcronが自動実行されなくなり、
// サーバーのcrontabからのみ実行されるようになる
ステップ5:WP-CLIとログでcronをデバッグする
# 登録済みcronイベントの一覧表示
wp cron event list
# 特定のcronイベントを今すぐ実行(テスト用)
wp cron event run my_daily_cleanup
# 期限が来ているすべてのcronを実行
wp cron event run --due-now
# cronスケジュールの一覧表示
wp cron schedule list
# cronイベントを手動で削除
wp cron event delete my_api_fetch
# wp-config.phpのDISABLE_WP_CRONがtrueかチェック
wp config get DISABLE_WP_CRON
// functions.php: cronの実行ログをWordPressのdebug.logに出力
add_action( 'my_daily_cleanup', function() {
if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
error_log( sprintf(
'[my_cron] %s を実行 - メモリ使用量: %s',
current_action(),
size_format( memory_get_usage() )
) );
}
// 処理内容...
} );
注意事項
wp_schedule_event()の第1引数のタイムスタンプはUTCのunixtimeです。time()はサーバーのタイムゾーン設定に依存するため、WordPress側ではtime()かcurrent_time('timestamp', true)(UTC)を使ってください。- wp_cronはページアクセス時に発火するため、アクセスのないサイトでは遅延が発生します。重要な定期処理にはサーバーcronと
DISABLE_WP_CRONの組み合わせを使ってください。 initフックでwp_next_scheduled()を確認せずにwp_schedule_event()を呼ぶと、ページリクエストのたびに重複登録されます。必ず登録済みか確認してから実行してください。
まとめ
wp_cronの実装は「cron_schedulesでカスタム間隔を追加→wp_next_scheduled()で重複確認後wp_schedule_event()でイベント登録→add_action()でフックに処理を実装→wp-config.phpでDISABLE_WP_CRON=trueにしてサーバーcronと連携→WP-CLIでデバッグ」の流れで整備します。関連記事:WordPressのトランジェントAPIでキャッシュを実装する方法、WordPressのショートコードを作成する方法。