2026年5月20日
2026年5月20日
WordPressのWP-Cronで定期処理を実装する方法
はじめに
WP-Cronはサイトへのアクセスをトリガーに定期処理を実行するWordPressの仕組みです。メールの定期送信・キャッシュのクリア・データの集計など、定刻に自動実行したい処理を wp_schedule_event で登録できます。
症状・原因
- 毎日自動でメールを送信したい
- 定期的にAPIからデータを取得したい
- キャッシュやログを自動でクリアしたい
- WP-Cronが実行されているか確認したい
解決手順
ステップ1:カスタムスケジュールを追加する
// functions.php
function mytheme_add_cron_intervals(array $schedules): array {
// 5分ごと
$schedules['every_five_minutes'] = [
'interval' => 300,
'display' => '5分ごと',
];
// 週2回(月・木)はWordPressでは難しいので、カスタムで対応
$schedules['twice_weekly'] = [
'interval' => 302400, // 3.5日
'display' => '週2回',
];
return $schedules;
}
add_filter('cron_schedules', 'mytheme_add_cron_intervals');
ステップ2:スケジュールイベントを登録する
// functions.php
// テーマ有効化時に登録
function mytheme_schedule_events(): void {
// 既に登録済みなら重複登録しない
if (!wp_next_scheduled('mytheme_daily_cleanup')) {
wp_schedule_event(
time(), // 初回実行時刻(Unixタイムスタンプ)
'daily', // スケジュール: hourly / twicedaily / daily / weekly
'mytheme_daily_cleanup' // フックのアクション名
);
}
if (!wp_next_scheduled('mytheme_fetch_api_data')) {
wp_schedule_event(time(), 'every_five_minutes', 'mytheme_fetch_api_data');
}
}
add_action('wp', 'mytheme_schedule_events');
// テーマ無効化時に解除(必須!)
function mytheme_clear_scheduled_events(): void {
$timestamp = wp_next_scheduled('mytheme_daily_cleanup');
if ($timestamp) {
wp_unschedule_event($timestamp, 'mytheme_daily_cleanup');
}
// 全スケジュールをまとめて解除
wp_clear_scheduled_hook('mytheme_fetch_api_data');
}
add_action('switch_theme', 'mytheme_clear_scheduled_events');
ステップ3:実際の処理を実装する
// functions.php
// 毎日のクリーンアップ処理
function mytheme_run_daily_cleanup(): void {
// 古いトランジェントを削除
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->options}
WHERE option_name LIKE '_transient_%'
AND option_name NOT LIKE '_transient_timeout_%'"
);
// 30日以上前のゴミ箱の投稿を完全削除
$old_trash = get_posts([
'post_status' => 'trash',
'posts_per_page' => -1,
'date_query' => [['before' => '30 days ago']],
'fields' => 'ids',
]);
foreach ($old_trash as $post_id) {
wp_delete_post($post_id, true);
}
// ログ記録
error_log('[mytheme cron] Daily cleanup completed: ' . gmdate('Y-m-d H:i:s'));
}
add_action('mytheme_daily_cleanup', 'mytheme_run_daily_cleanup');
// API データ取得処理
function mytheme_run_fetch_api_data(): void {
$cached = get_transient('mytheme_api_cache');
if ($cached !== false) {
return; // キャッシュが有効な間はスキップ
}
$response = wp_remote_get('https://api.example.com/data', [
'timeout' => 15,
]);
if (is_wp_error($response)) {
error_log('[mytheme cron] API fetch failed: ' . $response->get_error_message());
return;
}
$data = json_decode(wp_remote_retrieve_body($response), true);
if (!empty($data)) {
set_transient('mytheme_api_cache', $data, 300); // 5分キャッシュ
update_option('mytheme_api_last_fetch', gmdate('Y-m-d H:i:s'));
}
}
add_action('mytheme_fetch_api_data', 'mytheme_run_fetch_api_data');
ステップ4:単発実行(wp_schedule_single_event)
// functions.php: 1回だけ後で実行する
function mytheme_schedule_email_notification(int $user_id): void {
// 1時間後にメール送信
wp_schedule_single_event(
time() + HOUR_IN_SECONDS,
'mytheme_send_welcome_email',
[$user_id] // 引数は配列で渡す
);
}
function mytheme_send_welcome_email(int $user_id): void {
$user = get_userdata($user_id);
if (!$user) {
return;
}
wp_mail(
$user->user_email,
'ご登録ありがとうございます',
sprintf('%sさん、ご登録ありがとうございます。', $user->display_name)
);
}
add_action('mytheme_send_welcome_email', 'mytheme_send_welcome_email');
add_action('user_register', 'mytheme_schedule_email_notification');
ステップ5:サーバーCronでWP-Cronを確実に実行する
# crontab -e で追加(毎分実行)
* * * * * /usr/bin/php /var/www/html/wp-cron.php > /dev/null 2>&1
# またはWP-CLIを使う
* * * * * /usr/local/bin/wp --path=/var/www/html cron event run --due-now > /dev/null 2>&1
// wp-config.php: WP-Cronの自動実行を無効化(サーバーcronを使う場合)
define('DISABLE_WP_CRON', true);
注意事項
- WP-Cronはサイトへのアクセスがないと実行されません。トラフィックが少ないサイトでは、サーバーのcronと連携することを検討してください
wpフックでのイベント登録は、毎回wp_next_scheduledで重複確認が必要です。重複登録するとタスクが複数回実行されます- テーマ/プラグイン非有効化時に
wp_clear_scheduled_hookで必ず解除してください。残留するとエラーの原因になります
まとめ
cron_schedules フィルターでカスタム間隔を定義し、wp_next_scheduled で重複確認後に wp_schedule_event で登録します。処理は対応するフックに add_action で追加し、テーマ切り替え時に wp_clear_scheduled_hook で解除します。サーバーcronと組み合わせると確実に定刻実行できます。