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と組み合わせると確実に定刻実行できます。

お気軽にご相談ください

お見積りへ お問い合わせへ