Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Do-It-Yourself WordPress Scheduling: Mastering WP-Cron

by

As one of the lesser-used WordPress features, WP-Cron often gets overlooked by developers. Its applications, however, are no laughing matter. From caching to notifications to clean up, scheduling cron jobs can work to create a distinct advantage in even the most simple WordPress blog. Join in as we explore important applications of this very system.


Just an Average Cron Job? Think again.

Schedule

WP-Cron is not the same as the Unix cron scheduler...

Immediately upon seeing the word cron, I'm sure you've taken a stab at where we're headed: scheduling perfectly timed events to run at specified intervals. On the contrary, WP-Cron is not the same as the Unix cron scheduler. The key distinction lies in how it is run; unlike a background process, WP-Cron kicks in every time a visitor opens your WordPress-powered site. As such, it retains the vital characteristic of imprecise timing.

Yes, you read right: imprecise timing. Although the words cron and accuracy are like two peas in a pod, they do not harmonize in WordPress' system. But is this really a problem? If considered in the context of the user, this actually becomes an asset.

Let's take the example of a normal cron job running every five minutes to update some database information used on a website. If no visitors visit the site for 40 minutes, what, then, is the point of running this job eight times? All intermediate values would both be obsolete and unused. If, conversely, it were to kick in on the first user visit after a minimum of five minutes, it would not only accomplish the same job, but also prevent unnecessary updates. In other words, because WP-Cron is based on the user, it has the advantage of only running when visitors are present.


Don't Beat Around the Bush. Show Me!

To apply WP-Cron, let's consider the oft-used RSS managing application, FeedBurner. By far, one of the most popular features of this application is its ability to count RSS subscribers. Once indexed, a site's subscriber count can be accessed through a simple API call. It follows, then, that this API call can be done once per page view to deliver the subscriber count to viewers. This, however, leads to a problem.


Enter the World of Caching

If FeedBurner's API is accessed once per page view, it inevitably leads to an extra HTTP request—not to mention one from another domain—for each visitor. This increases the page load time for users.

To counteract this problem, it is important to make one key realization about this delivery method: an RSS subscriber count is unlikely to update on every single view of the page. In fact, FeedBurner only updates its count once per day. Even if it were to change rapidly, is it really necessary to display the latest count for every visitor? Does it matter that the count is slightly outdated, but subsequently refreshed within a day?

For our purposes, it is entirely useless to fetch the RSS subscriber count for each page view. Instead, if it is retrieved for one visitor, it can simply be reused for future ones. Then, after a day has passed, an update to this count can be made. Such a process is known as caching. After being updated, the RSS subscriber count is cached—stored for future use instead of being re-calculated—until a day has passed. And, with that, we enter the world of WP-Cron.


Step 1 Explore the Documentation

Documentation

To understand WP-Cron, it is important to know where documentation is available. WordPress.org provides summaries of each cron function in its Codex. To complete our previously defined task, we will need to look at the wp_schedule_event function, which requires four parameters:

  • Time: a UNIX timestamp specifying when the event should trigger
  • Recurrence: how often the event should be retriggered after the scheduled time
  • Hook: a hook used to add functionality when the event is triggered
  • Args: an array of arguments to pass to all hooked functions (optional)

Our event will trigger when the current time meets or exceeds the time passed to this function, as prescribed by a future visitor to the website. It will then retrigger based on the recurrence parameter, which can be set to hourly, twicedaily, daily, or none. Custom recurrence schedules may also be defined.

In order to deal with the event, a hook is used. In brief, a WordPress hook can be considered a placeholder for an action. Actions may be assigned to hooks via WordPress' add_action function. More specifically, to add a function handler to the given hook, one may call:

add_action( 'hook_name', 'function_name' );

where hook_name and function_name are the name of the hook and handling function, respectively.


Step 2 Calling the Function

Because FeedBurner updates once per day, we will specify a daily schedule, as per the code below:

wp_schedule_event( time(), 'daily', 'feedburner_refresh' );

Note that time() is the current UNIX timestamp in seconds. If run, the 'FeedBurner Update' hook will trigger immediately and then once per day afterward. Note that if we were to just put this in our WordPress functions.php file, it would schedule a new event on every single page load. This is not our desired functionality; rather, we only want to schedule this event once. The easiest way to do this is by simply checking whether the event is already scheduled. This can be done through the wp_next_scheduled function, which will return false if the event is not set to trigger in the future or the time of its next trigger otherwise:

if( !wp_next_scheduled( 'feedburner_refresh' ) ) {
   wp_schedule_event( time(), 'daily', 'feedburner_refresh' );
}

If we ever need to unschedule this event, it's as simple as calling the wp_unschedule_event function, which takes the same parameters—save for the recurrence—as wp_schedule_event. Note that the time passed must be the time of the next trigger, which can be retrieved via wp_next_scheduled:

if( false !== ( $time = wp_next_scheduled( 'feedburner_refresh' ) ) ) {
   wp_unschedule_event( $time, 'feedburner_refresh' );
}

We can also unschedule this event through its hook name using the wp_clear_scheduled_hook function. Be aware that this alternative will also remove all other events that use the same hook.

wp_clear_scheduled_hook( 'feedburner_refresh' );

Step 3 Deploying the Hook

Hook

Now that our event is scheduled, we must add a handler to it:

add_action( 'feedburner_refresh', 'update_rss_subscriber_count' );

This sets the function named update_rss_subscriber_count to be called once the feedburner_refresh hook is triggered. It is now time to write this function.


Step 4 Retrieving the FeedBurner Subscriber Count

To retrieve the subscriber count in the update_rss_subscriber_count function, we can make a call to FeedBurner's API via the URL <https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=[NAME]>, where [NAME] is the name of our feed.

This will return XML data in the following form:

<rsp stat="ok">
   <!--
      This information is part of the FeedBurner Awareness API. If you want to hide this information, you may do so via your FeedBurner Account.
   -->
   <feed id="8olmjno1k05rb1som1frr6u854" uri="nettuts">
      <entry date="2011-06-22" circulation="84673" hits="152325" reach="25865"/>
   </feed>
</rsp>

The information we are looking for is in the circulation attribute. The following regular expression can easily parse through the data for this value: circulation="(.*?)".

Put in English, our regular expression matches the following:

  • circulation= – The word circulation followed by an equals sign
  • "(.*?)" – Quotes and everything inside

Running this using the preg_match function will retrieve an array of matches which will contain the number of subscribers in the first index position. Putting this information together yields the following code:

// find the FeedBurner url and get the data from it
// change [NAME] to the name of your FeedBurner feed
$url = 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=[NAME]';
$data = @file_get_contents( $url ); // @ will surpress errors

// use a regular expression to parse the data
$regex = '%circulation="(.*?)"%';
preg_match( $regex, $data, $matches );

// get the resultant count if available
$count = false;
if( $matches && $matches[1] )
   $count = (int) $matches[1];

Step 5 Storing the Subscriber Count

Save

Now that we have retrieved the subscriber count, we'll need to store it for accessibility; instead of revisiting the API XML data, visitors will merely access this stored value.

Rather than creating a database or file for storage purposes, we can employ yet another WordPress feature: options. WordPress options are simple ways to store bits of data along with identifying names. Adding, deleting, and accessing options are as simple as the following functions:

  • update_option( $name, $value ) - Adds or updates an option with name $name and value $value.
  • delete_option( $name ) - Delete an option with name $name.
  • get_option( $name ) - Get the option value associated with name $name.

Although our subscriber count is not technically a configuration value, using WordPress options is one of the most convenient ways—if not the most convenient—for storing such simple data. Consequently, to store our subscriber count, we'll use the update_option method, which will not only override previous values, but also create the option in the first place:

// if a count could not be found, do not update
// instead, stick with the previous count
if( $count !== false )
   update_option( 'subscriber_count', $count );

Our function is complete! After setting up the event, retreiving the data via the FeedBurner API, and storing the desired value, all that's left to do is output! The full code for the scheduling and retrieval function—which you can place in functions.php—may be found below:

// schedule the feedburner_refresh event only once
if( !wp_next_scheduled( 'feedburner_refresh' ) ) {
   wp_schedule_event( time(), 'daily', 'feedburner_refresh' );
}

add_action( 'feedburner_refresh', 'update_rss_subscriber_count' );
function update_rss_subscriber_count() {
   // find the FeedBurner url and get the data from it
   // change [NAME] to the name of your FeedBurner feed
   $url = 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=[NAME]';
   $data = @file_get_contents( $url ); // @ will surpress errors

   // use a regular expression to parse the data
   $regex = '%circulation="(.*?)"%';
   preg_match( $regex, $data, $matches );

   // get the resultant count if available
   $count = false;
   if( $matches && $matches[1] )
      $count = (int) $matches[1];

   // if a count could not be found, do not update
   // instead, stick with the previous count
   if( $count !== false )
      update_option( 'subscriber_count', $count );
}

Step 6 Output

The subscriber count is now just a mere function call away in any template file:

echo get_option( 'subscriber_count' );

Conclusion

Finish

Our RSS subscriber count is now optimized; rather than being retrieved for each request, it is cached with the help of WP-Cron, saving our users time and reducing bandwidth usage. Because it only activates when our site actually receives a visitor, our function is lazy—a term that can certainly be considered good in this context. But alas, we have only uncovered one application of WP-Cron here; the rest is up to you.

Have your own innovative application of WP-Cron? Share it with us in the comments!

Advertisement