How to create a Cron Job in WordPress: Teach your plugin to do something automatically

pencil-iconCreating a recurring automatic function in WordPress used to be one of the most difficult things for me to understand. Several articles out there explain how to do it, yet I always forgot the concepts when the next cron job job came along. Right now it’s in my head, and that’s the time when I like to write things down for “next time”. I hope these notes will help you in your own development.

Setting up a Cron Job in WordPress involves the following items:

  1. a scheduled event, i.e. something that WordPress will execute repeatedly
  2. our own function with code to execute (we’ll hook it into the above)
  3. the event needs to be run when WordPress loads
  4. the event needs to be unscheduled upon plugin deactivation

So we’re hooking into WordPress, which gives us a new “timed hook” into which we hook our own function. No wonder this is a complex subject.

In addition, WordPress only offers three schedules, so we’ll also look into how to add our own intervals. Let’s get started.

Creating our Scheduled Event

First we’ll create a function that will schedule our event. Mine is called “mycronjob” and it will run once every day. All this code can go into your plugin’s main file, outside the main function:

// create a scheduled event (if it does not exist already)
function cronstarter_activation() {
	if( !wp_next_scheduled( 'mycronjob' ) ) {  
	   wp_schedule_event( time(), 'daily', 'mycronjob' );  
	}
}
// and make sure it's called whenever WordPress loads
add_action('wp', 'cronstarter_activation');

At the same time we want to make sure it’s unscheduled when the plugin is deactivated:

// unschedule event upon plugin deactivation
function cronstarter_deactivate() {	
	// find out when the last event was scheduled
	$timestamp = wp_next_scheduled ('mycronjob');
	// unschedule previous event if any
	wp_unschedule_event ($timestamp, 'mycronjob');
} 
register_deactivation_hook (__FILE__, 'cronstarter_deactivate');

Now we have a hook called “mycronjob” which will be called once every day. Let’s add our own function to it:

Adding your Repeat Function

To prove that this is working we’ll send an email in this example – this is just a placeholder for your own code you’d like to run on a recurring basis:

// here's the function we'd like to call with our cron job
function my_repeat_function() {
	
	// do here what needs to be done automatically as per your schedule
	// in this example we're sending an email
	
	// components for our email
	$recepients = 'you@example.com';
	$subject = 'Hello from your Cron Job';
	$message = 'This is a test mail sent by WordPress automatically as per your schedule.';
	
	// let's send it 
	mail($recepients, $subject, $message);
}

// hook that function onto our scheduled event:
add_action ('mycronjob', 'my_repeat_function'); 

Note how we’re adding the function to your specified event in the last line of code.

In all likelihood – and definitely for testing purposes – you may not be able to sit and wait an entire day for this email to be sent. Hence we need a more immediate schedule. Let’s tackle that next.

Creating Custom Intervals

By default, WordPress provides the following time intervals you can use:

  • daily
  • twicedaily
  • hourly

You can add your own intervals too: here’s an example in which we’re creating an interval that runs once every minute:

// add custom interval
function cron_add_minute( $schedules ) {
	// Adds once every minute to the existing schedules.
    $schedules['everyminute'] = array(
	    'interval' => 60,
	    'display' => __( 'Once Every Minute' )
    );
    return $schedules;
}
add_filter( 'cron_schedules', 'cron_add_minute' );

We’re adding an array called “everyminute” to the existing default intervals. You specify this in seconds and give it a display name that describes what it does.

To use this interval you need to create your scheduled event with the array name. To stick with the above example, here’s how we’d create our “mycronjob” event once every minute:

// create a scheduled event (if it does not exist already)
function cronstarter_activation() {
	if( !wp_next_scheduled( 'mycronjob' ) ) {  
	   wp_schedule_event( time(), 'everyminute', 'mycronjob' );  
	}
}
// and make sure it's called whenever WordPress loads
add_action('wp', 'cronstarter_activation');

The unschedule function remains the same as above.

Checking and Testing your Scheduled Events

Before you go on a coding spree you probably want to know if this event is actually happening as planned. I like to do this in two ways.

Setup something tangible like the email function above and set the schedule to something like once every minute. Then refresh the front page of your WordPress test instance once or twice and watch your inbox. You should receive emails more or less once a minute, if you keep refreshing the front page (not the admin page). If this works, then you’re good to go.

Another way to check if your event is recognised by WordPress is a lovely plugin by Simon Wheatly called Cron View:

http://wordpress.org/plugins/cron-view/

Once activated it will show you which events are scheduled by WordPress. Let me show you how helpful this is. The first screenshot shows a vanilla WordPress installation with its own scheduled events. “mycronjob” is nowhere to be seen (nor should it at this point):

Screen Shot 2014-01-17 at 17.11.57

Now we’ll activate my own cron starter plugin and refresh the front page. We’ll also refresh the What’s In Cron page to see this:

Screen Shot 2014-01-17 at 17.12.34

Just what the doctor ordered: “mycronjob” is scheduled to run in the next minute, and at the top of the screen I can see my custom schedule that have been added (Once every Minute). You can see this menu under Tools – What’s In Cron.

Thanks, Simon!

Final Thoughts

WordPress Scheduled Events are not “real” Cron Jobs, like the UNIX Cron Tab. The difference is that a “real” cron job would be reliably called by the server clock. Scheduled Events on the other hand are determined by how long ago the last event happened. If the time interval between “last run” and “right now” is larger than specified, the event fires.

This in turn relies on visitor traffic. On low or no-traffic websites like your test environment this means your event may not fire as expected. You can help this along by refreshing your front page.

Also note that traffic kicking off scheduled events can be disabled in wp-config.php by adding the following line:

define('DISABLE_WP_CRON', 'true');

This is often done so that a “real” cron job can call the wp-cron.php file in exactly specified intervals (we’ll deal with this in another article). It’s not the default setting, but definitely something to check if your events are not working as expected.

Demo Project

I have created a demo project on GitHub that implements the above and works out of the box:

Happy Automation!





Jay is the CEO and founder of WP Hosting, a boutique style managed WordPress hosting and support service. He has been working with Plesk since version 9 and is a qualified Parallels Automation Professional. In his spare time he likes to develop iOS apps and WordPress plugins, or draw on tablet devices. He blogs about his coding journey at http://wpguru.co.uk and http://pinkstone.co.uk.