While I was developing my latest WordPress plugin (WP Get Products from Amazon API), I realized I have to use CRON job functionality in the plugin. Cron jobs are used for scheduling tasks to run on the server and in this case I had to daily update products stored in the database. So, utilizing a CRON job was the obvious choice. WordPress has a neat function wp_schedule_event which does the heavy-lifting for your. Let’s have a look at the function:
wp_schedule_event( int $timestamp, string $recurrence, string $hook, array $args = array() )
So, the function takes 4 parameters:
$timestamp – defines when to run the event for the first time
$recurrence – defines how often to run the event. Default options are hourly, twicedaily and daily.
$hook – defines action hook to execute when the event runs
$args – array of arguments to pass to the hook’s callback function (optional)
So, in procedural code you would do something like shown below:
register_activation_hook( __FILE__, 'activate_plugin' );
function activate_plugin() { // runs on plugin activation
if ( ! wp_next_scheduled( 'plugin_cron_refresh_cache' ) ) {
wp_schedule_event( time(), 'daily', 'plugin_cron_refresh_cache' ); // plugin_cron_refresh_cache is a hook
}
};
// hook a function
add_action( 'plugin_cron_refresh_cache', 'plugin_do_stuff_daily' );
// function that will run daily
function plugin_do_stuff_daily() {
// your code that will run once per day
}
Note the use of wp_next_scheduled function which checks if CRON job is already registered. That prevents us from registering more than one same CRON job. Imagine somebody is activating and deactivating your plugin. Without this function you will suddenly have numerous same CRON jobs registered. Here is more information about this function. If your code is procedural, that’s all you need to set a CRON job. However, my plugin used Devin Vinson’s WordPress Plugin Boilerplate as a foundation. Hence, I had to add CRON job in this context.
Adding CRON job to WordPress Plugin Boilerplate
Typically you would add a CRON job to the admin side of the plugin, but in my case it made more sense to add it to the public side.
So, first I edited the Activator class in includes/class-wp-gpfa-activator.php. To the activate method (public static function activate()) I added the following:
// schedule cron job
if ( ! wp_next_scheduled( 'gpfa_cron_refresh_cache' ) ) {
wp_schedule_event( time(), 'daily', 'gpfa_cron_refresh_cache' );
}
The next step was to hook a function to the gpfa_cron_refresh_cache hook. For this I edited the main class in includes/class-wp-gpfa.php. To the define_public_hooks method (private function define_public_hooks()) I added the following:
$this->loader->add_action( 'gpfa_cron_refresh_cache', $plugin_public, 'update_cache_in_the_background' );
Now the update_cache_in_the_background function will run once daily. The update_cache_in_the_background method should go in the public class in public/class-wp-gpfa-public.php.
public function update_cache_in_the_background() {
// do stuff once daily
}
Now it’s time to check if we successfully added CRON job. First, we need to deactivate and reactivate the plugin so that the CRON job actually gets registered. Remember, the register function runs on activation. After that we use a handy plugin called WP Crontrol. Our function/method should be shown in the plugin as on the image below.
And that’s it, we have successfully added CRON job to a WordPress plugin build on top of WordPress Plugin Boilerplate. Note that you should also deregister CRON on plugin deactivation. You can do this with the wp_clear_scheduled_hook function. Read more about this here.
Questions and comments are welcome! 🙂
Thank you so much, there not so much info about this on internet mostly the articles found says about install the “WP Crontrol plugin” but not how to create a cron job from scratch, thank you again.
You are welcome 🙂
Hi Blaz,
Thanks for this, was really searching for an explanation like this. So I have a question, what is the best way to add a custom cron schedule?
Hi Walter,
To add a custom schedule, you can use the cron_schedules filter. See example under User Contributed Notes here: https://developer.wordpress.org/reference/functions/wp_get_schedules/
Regards,
Blaz
Thank you so much Blaz !
I just spent more than 4 hours with my plugin and internet to add a scheduled tasks (WP CRON) without success ;(
I can’t understand why my hook was never called when cron job was launched
BUT
as I use WordPress Plugin Boilerplate
AND
your article is GREAT and WORKS at first time (I just followed your instructions)
WELL
I can go to WE happy !
Thanks for sharing that !!!
Happy to hear that! 🙂