Mastering WordPress Cron for Scheduling Events

Mastering WordPress Cron for Scheduling Events

WordPress Cron is one of the most useful features that you’ll want to learn and understand if, like me, you spend a great deal of time working with WordPress.Being able to run certain functions on a tight schedule is essential for any CMS and WordPress has a set of functions which help make this process very simple and almost effortless.

In this article I will cover the following WordPress Cron features:

  • How is WordPress Cron different than your normal Cron
  • Scheduling a recurring event
  • Scheduling a single event
  • Un-scheduling an event
  • Specifying custom Cron intervals

What is Cron?

You are probably familiar with the term ‘Cron’ as it relates to the time-based scheduler in Unix systems and although WordPress’ Cron is different; the main idea behind it is the same.

Some examples of how WordPress is using it’s Cron system internally is checking for theme and plugin updates and even checking if there are posts ready to be published.

How is WordPress Cron Different?

If you are familiar with Unix’s Cron, you probably think that WordPress’ Cron is always on the lookout for new tasks and running them as they come. This is far from the truth and I’ll explain why shortly.

WordPress’ Cron runs when a page is loaded, whether it’s a front-end or back-end page. In other words, when a page is loaded on your website, WordPress will check if there are any tasks or events that need to run and execute them. If you are thinking this is not ideal, you are absolutely right.

If you happen to have a website that doesn’t get too much traffic and you have a task that needs to be executed at a precise time, WordPress will not know the task is due until someone visits your website. Even if it happens to be a search engine bot crawling your website.

Scheduling Events with Cron

There are two flavors of Cron events that you can schedule with a few lines of code:

  • Single events – run only once and never again until it is rescheduled again.
  • Recurring events – run on a schedule and is set to re-occur indefinitely using a time interval.

Scheduling a Recurring Event

Scheduling a recurring event requires that you create a custom ‘Action’ which must also be registered with Cron. Once the Cron runs, the function attached to the custom ‘Action’ you created earlier is executed.

Let’s take a look at the following example where we are going to be deleting post revisions on a daily basis.

First we create our custom ‘Action’ which will have attached to it the function we want to run when the hook is called by Cron.

 <?php  
 // delete_post_revisions will be call when the Cron is executed  
 add_action( ‘delete_post_revisions’, ‘delete_all_post_revisions’ );

// This function will run once the ‘delete_post_revisions’ is called  
 function delete_all_post_revisions() {

 $args = array(  
 ‘post_type’ => ‘post’,  
 ‘posts_per_page’ => -1,  
 // We don’t need anything else other than the Post IDs  
 ‘fields’ => ‘ids’,  
 ‘cache_results’ => false,  
 ‘no_found_rows’ => true  
 );

 $posts = new WP_Query( $args );

 // Cycle through each Post ID  
 foreach( (array)$posts->posts as $post_id ) {

 // Check for possible revisions  
 $revisions = wp_get_post_revisions( $post_id, array( ‘fields’ => ‘ids’ ) );

 // If we got some revisions back from wp_get_post_revisions  
 if( is_array( $revisions ) && count( $revisions ) >= 1 ) {

 foreach( $revisions as $revision_id ) {

 // Do a final check on the Revisions  
 if( wp_is_post_revision( $revision_id ) ) {  
 // Delete the actual post revision  
 wp_delete_post_revision( $revision_id);  
 }  
 }  
 }  
 }  
 }  

For scheduling the recurring event we make use of the wp_schedule_event( $timestamp, $recurrence, $hook, $args ) function which takes 4 arguments:

  • $timestamp — (integer) (required) The first time that you want the event to occur. This must be in a UNIX timestamp format. WP cron uses UTC/GMT time, not local time. Use time(), which is always GMT in WordPress. (current_time( ‘timestamp’ ) is local time in WordPress.)
  • $recurrence — (string) (required) How often the event should reoccur. Valid values are ‘hourly‘, ‘twicedaily‘ and ‘daily‘. We’ll see how to create our own time intervals later.
  • $hook — (string) (required) The name of an action hook to execute.
  • $args — (array) (optional) Arguments to pass to the hook function(s).

First we make sure the event has not been scheduled before and if it hasn’t, we go ahead and schedule it.

 <?php  
 // Make sure this event hasn’t been scheduled  
 if( !wp_next_scheduled( ‘delete_post_revisions’ ) ) {  
 // Schedule the event  
 wp_schedule_event( time(), ‘daily’, ‘delete_post_revisions’ );  
 }  

Note that you can also add tie this snippet of code to an action. If you are a plugin writer,
you could set up the scheduled event to run the first time the plugin options page is visited.
For a much simpler example, we are going to tie it to WordPress’ init action.

 <?php  
 // Add function to register event to WordPress init  
 add_action( ‘init’, ‘register_daily_revision_delete_event’);

// Function which will register the event  
 function register_daily_revision_delete_event() {  
 // Make sure this event hasn’t been scheduled  
 if( !wp_next_scheduled( ‘delete_post_revisions’ ) ) {  
 // Schedule the event  
 wp_schedule_event( time(), ‘daily’, ‘delete_post_revisions’ );  
 }  
 }  

Now that you know how to schedule recurring events, let’s take a look at creating a single event which will never run again until it is rescheduled.

Scheduling a Single Event

Just as its name suggests, a single event is one that runs once and then it stops. This single event can still be rescheduled again if needed.

The concept behind it is the same as the recurring events. First you register a custom hook which is called by Cron when it runs on the server. Once Cron calls the hook, its function is executed and that’s basically how you get things done.

As an example, we are going to be setting an expiration date for posts. Posts will expire 30 days after being published. We are going to be hooking into the publish_post so that we can schedule our single event as soon as the post is published and count down begins.

Setting up the function which will delete the post after 30 days.

 <?php

// delete_post_after_expiration will be called by Cron  
 // We are going to be passing the Post ID so we need to specify that  
 // we’ll need 1 argument passed to the function  
 add_action( ‘delete_post_after_expiration’, ‘delete_post_after_expiration’, 10, 1 );

// This function will run once the ‘delete_post_after_expiration’ is called  
 function delete_post_after_expiration( $post_id ) {

 // Takes care of deleting the specified Post  
 wp_delete_post( $post_id, true );  
 }  

Pretty simple, right? Now we need to schedule the event once the post is actually published. In order to accomplish this task we need to use the wp_schedule_single_event( $timestamp, $hook, $args ) function which takes 3 arguments.

  • $timestamp — (integer) (required) The time you want the event to occur. This must be in a UNIX timestamp format.
  • $hook — (string) (required) The name of an action hook to execute.
  • $args — (array) (optional) Arguments to pass to the hook function.

Here is quick look at how all this actions and hooks are put together.

 <?php

// schedule_post_expiration_event runs when a Post is Published  
 add_action( ‘publish_post’, ‘schedule_post_expiration_event’ );

function schedule_post_expiration_event( $post_id ) {

 // Schedule the actual event  
 wp_schedule_single_event( 30 * DAY_IN_SECONDS, ‘delete_post_after_expiration’, array( $post_id ) );  
 }  

We are using some time constants that WordPress has in place to make our lives easier. For more information on these constants, you can go to “Using Time Constants“, but here is a quick overview:

  • MINUTE_IN_SECONDS = 60 (seconds)
  • HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS
  • DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS
  • WEEK_IN_SECONDS = 7 * DAY_IN_SECONDS
  • YEAR_IN_SECONDS = 365 * DAY_IN_SECONDS

Un-scheduling Events

Now that you know how to schedule recurring and single events, it’s also going to be useful to know how to un-schedule these events.

You might be wondering, why would you want to un-schedule events? There is a good reason, particularly if you include some sort schedule events in your plugins.

Crons are stored on the wp_options table and by simply deactivating and deleting your plugin. WordPress will still try to run your events even though said plugin is no longer available. Having said that, please make sure you un-schedule events properly within your plugin or custom implementation.

Un-scheduling Cron events is relatively easy, all you need to know is the name of the hook and when is the next scheduled time that particular Cron is supposed to run. We are going to be using wp_next_scheduled() to find when the next occurrence will take place and only then we can un-schedule it using wp_unschedule_event().

Considering our first example, we would un-schedule the event the following way.

 <?php

// Get the timestamp of the next scheduled run  
 $timestamp = wp_next_scheduled( ‘delete_post_revisions’ );

// Un-schedule the event  
 wp_unschedule_event( $timestamp, ‘delete_post_revisions’ );  

Customizing Cron Intervals

It is possible to set custom Cron intervals which you can use when scheduling events using Cron. To do so, we just need to hook into the cron_schedules filter and add our own. Let’s take a look at adding a custom interval set to run every 10 minutes.

<?php  
 // Add custom cron interval  
 add_filter( ‘cron_schedules’, ‘add_custom_cron_intervals’, 10, 1 );

function add_custom_cron_intervals( $schedules ) {  
 // $schedules stores all recurrence schedules within WordPress  
 $schedules[‘ten_minutes’] = array(  
 ‘interval’ => 600, // Number of seconds, 600 in 10 minutes  
 ‘display’ => ‘Once Every 10 Minutes’  
 );

 // Return our newly added schedule to be merged into the others  
 return (array)$schedules;  
 }  

Conclusion

Using WordPress’ Cron couldn’t be any easier and it is a very nice and interesting tool which is sure to help you make your plugin more robust. Learning all these functions and putting them into practice with real world applications is the best way to master WordPress’ Cron for scheduling events.