Handling WP_Cron In a Multisite Enviroment

WP_Cron is a great utility that is native to WordPress.   Much like the crontab on your server allows scripts to execute at a scheduled time, WP_Cron gives WordPress plugins this same functionality.    While it sounds like a great feature, and it we can certainly turn it into one, out of the box it does have a few faults.   Unlike a crontab that executes at a specified time, WP_Cron relies on a user to load your website to run which can cause time sensitive tasks to be delayed and can have a significant impact on website performance.

Step 1: Disable WP_Cron

The solution to this problem is to move WP_Cron out of the WordPress initialization process and into the crontab, where we can set it to run at the top of every minute.   If you’ve ever worked on a WordPress website before you should recognize most of this process, however we will have to add an additional step to support a multisite installation.    For now the process remains the same, to disable WP_Cron we need to add the line define('DISABLE_WP_CRON', true); inside wp-config.php.

Step 2: Handle Multisite

To prevent having to repeat this process every time you add or remove a site to your multisite installation, we need to create a new file. This file will live in the root directory of your WordPress installation and reference your current blogs, so that WP_Cron runs on all of your active websites. In the root directory of your WordPress install, create a file named wp-cron-multisite.php, and inside it paste the following code:

<?php
/**
* When called via CURL this script will fetch an array of all active
* blogs and cycle through the array calling WP_Cron for each.
*
* @param author Arthur Guy <arthur@ajginteractive.com>
* @param website http://www.ajginteractive.com
* @param create-date 2015-03-07
* @param modify-date 2018-04-09
*/
 
//Extend WordPress
require('./wp-load.php');
 
//Get the blog list
global $wpdb;
$sql = $wpdb->prepare("SELECT path, blog_id FROM " . $wpdb->blogs . " WHERE deleted != 1 LIMIT 0,300", '');
$blogs = $wpdb->get_results($sql);
 
foreach ($blogs as $blog) {
 
//Get the URL with HTTP(s) prefix
$sql = $wpdb->prepare('SELECT option_value FROM ' . str_replace("_1_", "_", str_replace("_blogs", "", $wpdb->blogs) . "_" . $blog->blog_id . "_options") . ' WHERE option_name = "siteurl" LIMIT 0,1', '');
$options = $wpdb->get_results($sql);
 
//Setup the CURL request
$request = $options[0]->option_value . ($blog->path ? $blog->path : '/') . 'wp-cron.php?doing_wp_cron';
 
//CURL Request
$ch = curl_init($request);
$rc = curl_setopt($ch, CURLOPT_RETURNTRANSFER, FALSE);
$rc = curl_exec($ch);
curl_close($ch);
 
}
?>

Step 3: Add WP_Cron to the Crontab

Now that we have added support for multisite, the last step is to add WP_Cron to the server’s crontab. To do so open your crontab and add the following line, making sure to update domain.com with the primary domain that points to your server * * * * * wget -q -O - http://www.domain.com/wp-cron-multisite.php >>/dev/null 2>&1.

That’s it, you’re done and you’ll never have to worry about WP_Cron running late or failing to run for new websites on your multisite installation.