wp_schedule_event()
Schedule a recurring event.
Schedules a hook which will be triggered by WordPress at the specified interval. The action will trigger when someone visits your WordPress site if the scheduled time has passed.
Valid values for the recurrence are 'hourly', 'daily', and 'twicedaily'. These can be extended using the cron_schedules filter in wp_get_schedules().
Use wp_next_scheduled() to prevent duplicate events.
Use wp_schedule_single_event() to schedule a non-recurring event.
Hooks from the function
Return
true|false|WP_Error
. True if event successfully scheduled. False or WP_Error on failure.
Usage
wp_schedule_event( $timestamp, $recurrence, $hook, $args, $wp_error );
- $timestamp(int) (required)
- Unix timestamp (UTC) for when to next run the event.
- $recurrence(string) (required)
- How often the event should subsequently recur. See wp_get_schedules() for accepted values.
- $hook(string) (required)
- Action hook to execute when the event is run.
- $args(array)
- Array containing arguments to pass to the hook's callback function. Each value in the array is passed to the callback as an individual parameter. The array keys are ignored.
Default: empty array - $wp_error(true|false)
- Whether to return a WP_Error on failure.
Default: false
Examples
#1 Create a cron task when a plugin is activated
Let's schedule an hourly action for the plugin. To do this, call wp_schedule_event() when the plugin is activated (if we do not do it when activated, we will get many scheduled events!).
// Add a cron job when the plugin is activated register_activation_hook( __FILE__, 'my_activation' ); // Delete cron job when de-activating the plugin register_deactivation_hook( __FILE__, 'my_deactivation'); // php function to be executed when a cron event occurs add_action( 'my_hourly_event', 'do_this_hourly' ); function my_activation() { // delete all the same cron tasks just in case, so that // add new ones with a "clean slate" it may be necessary, // if the same task was connected incorrectly before (without checking if it already exists). wp_clear_scheduled_hook( 'my_hourly_event' ); // check if there is already a task with the same hook // this item is not needed, because we deleted all tasks above... // if( ! wp_next_scheduled( 'my_hourly_event' ) ) // add a new cron task wp_schedule_event( time(), 'hourly', 'my_hourly_event'); } function do_this_hourly() { // do something every hour } function my_deactivation() { wp_clear_scheduled_hook( 'my_hourly_event' ); }
#2 Create a cron job if it does not already exist
This example does not rely on activating a plugin (via the plugins directory), instead it adds an event if it does not exist:
// add a planned hook add_action( 'wp', 'add_my_cron_event' ); // add a cron-task function add_action( 'my_hourly_event', 'do_this_hourly' ); function add_my_cron_event() { if( ! wp_next_scheduled( 'my_hourly_event' ) ) { wp_schedule_event( time(), 'hourly', 'my_hourly_event'); } } function do_this_hourly() { // do something every hour }
#3 Adding a new interval
To add a new Cron interval in WordPress, use the filter cron_schedules.
Let's add a "5 minute" interval (do something every 5 minutes):
// add the 5-minute interval add_filter( 'cron_schedules', 'cron_add_five_min' ); // register the event add_action( 'wp', 'my_activation' ); // add a function to the specified hook add_action( 'my_five_min_event', 'do_every_five_min' ); function cron_add_five_min( $schedules ) { $schedules['five_min'] = array( 'interval' => 60 * 5, 'display' => 'Once every 5 minutes' ); return $schedules; } function my_activation() { if ( ! wp_next_scheduled( 'my_five_min_event' ) ) { wp_schedule_event( time(), 'five_min', 'my_five_min_event' ); } } function do_every_five_min() { // do something every 5 minutes }
WordPress constants that may come in handy when creating a cron interval:
HOUR_IN_SECONDS
- hour in seconds - 60*60 = 3600DAY_IN_SECONDS
- day in seconds - 60*60*24 = 86400WEEK_IN_SECONDS
- week in seconds - 60*60*24*7 = 604800
#4 Another example of creating a WP cron task (working example)
What the example does: gets the exchange rate of the ruble against the dollar and writes the result in the options. It is done only 2 times a day. Then, where necessary, the data can be quickly obtained from the option, where it was written.
Getting currency data works based on the [PHP Simple HTML DOM Parse] library (https://simplehtmldom.sourceforge.io/).
Note: But for today it's better to use modern lib to parse HTML: https://github.com/imangazaliev/didom
// Cron // Register the schedule when the plugin is activated register_activation_hook( __FILE__, 'activation_geting_dollar_rate' ); // Delete the schedule when the plugin is deactivated register_deactivation_hook( __FILE__, 'deactivation_geting_dollar_rate' ); // Hook and function to be executed by Cron add_action( 'geting_dollar_rate', 'get_real_dollar_rate' ); // Checking the existence of the schedule while the plugin is running, just in case if( ! wp_next_scheduled( 'geting_dollar_rate' ) ){ wp_schedule_event( time(), 'twicedaily', 'geting_dollar_rate' ); } function activation_geting_dollar_rate() { wp_clear_scheduled_hook( 'geting_dollar_rate' ); wp_schedule_event( time(), 'twicedaily', 'geting_dollar_rate' ); } function deactivation_geting_dollar_rate() { wp_clear_scheduled_hook( 'geting_dollar_rate' ); } function get_real_dollar_rate() { include 'inc/simple_html_dom.php'; $html = file_get_html( 'https://news.yandex.ru/quotes/1.html' ); $value = $html->find( '.quote_current_yes', 0 )->find( '.quote__value', 0 )->plaintext; $date = $html->find( '.quote_current_yes', 0 )->find( '.quote__date', 0 )->plaintext; $rate = [ 'dollar' => $value, 'date' => $date, 'check' => current_time( 'mysql', 1 ) ]; update_option( 'i_price_dollar_rate', $rate, 'no' ); } // returns dollar rate function get_dollar_rate( $data = null ) { $rate = get_option( 'i_price_dollar_rate' ); if( ! $data || $data === 'dollar' ){ return $rate['dollar']; } if( $data === 'date' ){ return $rate['date']; } if( $data === 'check' ){ return $rate['check']; } }
#5 Updating a task that has not yet been completed
Suppose we have a setting in the plugin for the interval of some cron-task. And we need to update the task interval depending on this setting.
The first thing to do is to delete the current task and add a new one. You should also consider changing the setting when you change the interval for the cron task.
This example shows how to do such operation with ACF plugin. When you update an option of which you need to update the cron task.
// function of cron task execution 'rs_cron_event' add_action( 'rs_cron_event', 'rs_cron_rebuild_meta_products' ); // add our new interval for the crone add_filter( 'cron_schedules', 'rs_cron_interval' ); // Field update function add_filter( 'acf/update_value/name=rs_time_period', 'my_acf_update_value', 10, 3 ); function rs_cron_rebuild_meta_products() { // perform a cron job $headers = 'From: My Name <[email protected]>' . "\r\n"; wp_mail( '[email protected]', 'Theme', 'Content', $headers ); } function rs_cron_interval( $schedules, $value = '' ){ // to be able to specify the value rigidly if( ! $value ) { $value = intval( get_option('options_rs_time_period') ?: 12 ); } $schedules['rs_time_period'] = array( 'interval' => $value * HOUR_IN_SECONDS , 'display' => 'Specified in the RS plugin settings' ); return $schedules; } function my_acf_update_value( $new_period, $post_id, $field ) { $old_period = get_option( 'options_rs_time_period' ); // the option has changed, let's overwrite the cron job with the new setting! if( $new_period != $old_period ){ // delete the existing cron task $timestamp = wp_next_scheduled( 'rs_cron_event' ); wp_unschedule_event( $timestamp, 'rs_cron_event'); // let's change the interval so that the task is added correctly... add_filter( 'cron_schedules', function( $schedules ) use ( $new_period ){ // crank the interval hard return rs_cron_interval( $schedules, $new_period ); } ); // add the cron task again wp_reschedule_event( time(), 'rs_time_period', 'rs_cron_event' ); } return $new_period; }
#6 A simple class for conveniently adding WP CRON Events
See the article Kama_Cron.
#7 Schedule event with multiple arguments (Parameters)
Arguments must be passed as elements of an index array.
register_activation_hook( __FILE__, 'my_activation' ); function my_activation() { $args = [ $args_1, $args_2 ]; if ( ! wp_next_scheduled ( 'my_hourly_event', $args ) ) { wp_schedule_event( time(), 'hourly', 'my_hourly_event', $args ); } }
Don't forget to specify how many arguments the function should get - the 4th parameter add_action().
add_action( 'my_hourly_event', 'do_this_hourly', 10, 2 ); function do_this_hourly( $args_1, $args_2 ) { // do something every hour }
Don’t forget to clean the scheduler on deactivation:
register_deactivation_hook( __FILE__, 'my_deactivation' ); function my_deactivation() { // delete all events regardless of the arguments wp_unschedule_hook( 'my_hourly_event' ); // OR remove single event by specifying it's parameters wp_clear_scheduled_hook( 'my_hourly_event', [ $args_1, $args_2 ] ); }
#8 Set WP CRON Trigger on Server side
It should be noted that depending on how resource-intensive your hook is, the default behavior of “Waiting until a user visits the site” may not be suitable. Of course you should try to make your code as efficient as possible – but if you have a specific case where it’s still resource intensive you do not want to keep the user sitting on a white screen while your hook does it’s work.
For specific situations you might want to consider disabling WP’s internal CRON by placing this line into the wp-config.php
file:
define('DISABLE_WP_CRON', 'true');
Then create a CRON job on your server (using your hosting control panel or crontab -e
command) to fetch the URL:
https://example.com/wp-cron.php?doing_wp_cron
OR execute:
/usr/bin/php -q /path-to-your-wp-installation/wp-cron.php
Changelog
Since 2.1.0 | Introduced. |
Since 5.1.0 | Return value modified to boolean indicating success or failure, pre_schedule_event filter added to short-circuit the function. |
Since 5.7.0 | The $wp_error parameter was added. |