Multisite - Professional WordPress: Design and Development, 3rd Edition (2015)

Professional WordPress: Design and Development, 3rd Edition (2015)

Chapter 10. Multisite

WHAT’S IN THIS CHAPTER?

· Understanding WordPress Multisite

· Differences between Multisite and standard WordPress

· Installing and configuring a Multisite network

· Coding for Multisite

· Multisite database schema

WROX.COM CODE DOWNLOADS FOR THIS CHAPTER

The wrox.com code downloads for this chapter are found at www.wrox.com/go/wordpress3e on the Download Code tab. The code is in the Chapter 10 download file and individually named according to the code file names throughout the chapter.

WordPress Multisite is a powerful core feature in WordPress. When enabled, Multisite allows you to create multiple websites with a single install of WordPress. This makes it easy to rapidly launch new WordPress websites. A Multisite network can even allow open user and site registration, enabling anyone to create a new site in your network. The largest WordPress Multisite network is WordPress.com, which is a great example of what Multisite can be.

WHAT IS MULTISITE?

Prior to WordPress 3.0, Multisite was called WordPress MU (or multi-user) and was a separate software package that needed to be downloaded and installed. WordPress 3.0 merged MU into the core of WordPress, and WordPress Multisite was born.

Multisite is not enabled by default, so it’s important to understand the differences before enabling Multisite in your WordPress installation.

Multisite Terminology

It’s important to understand the terminology used throughout this chapter when working with WordPress Multisite. Two important terms in Multisite are network and site. A network is the entire Multisite installation, or the network. A site is a single site inside the network. Therefore, WordPress Multisite is a network of sites.

Another important term is Blog ID. The Blog ID is a unique ID assigned to every new site created in Multisite. Many of the functions and code examples will reference the Blog ID. Sometimes this is also referred to as the site ID. Remember that WordPress was originally built as a blogging platform but has evolved over the years into a full-fledged content management system. Therefore, many of the functions and code in WordPress still reference items as “blogs” when really they are sites.

NOTE Don’t let the term “blog” confuse you. A blog in WordPress Multisite is actually a site in the network. A Blog ID, as referred to by many functions and code examples, is the unique ID of the site in the network.

Differences

When you install standard WordPress, you are installing a single website to run on WordPress. WordPress Multisite enables you to run an unlimited number of websites with a single install of WordPress. When enabling Multisite, you need to determine how sites will be viewed in WordPress, either using subdomains or subdirectories. The following is an example of both:

Subdirectory Example

· http://example.com/site1

· http://example.com/site2

Subdomain Example

· http://site1.example.com/

· http://site2.example.com/

As you can see, this is a pretty big decision and one that should be carefully considered. With a plugin, there are ways to map top-level domains to any site in your network (i.e., http://mywebsite.com), which is covered later on in this chapter.

Themes and plugins are also treated differently in Multisite. Individual site administrators can enable themes and plugins on their site, but they can’t install them.

WordPress Multisite also introduces a new user role: Super Admin. Super Admin users have access to the Network Admin section of Multisite. This section is where all Multisite configuration occurs. Super Admins also have full access to every site in the Multisite network, whereas normal Administrators only have access to the site they are an administrator of.

Advantages of Multisite

WordPress Multisite has a number of advantages over standard WordPress. The biggest advantage of Multisite is that you have a single install of WordPress to administer. This makes updates for WordPress core, themes, and plugins much easier. If you have a WordPress Multisite network of 50 sites, and a plugin update is released, you need to update that plugin only once and it will affect all sites in your network. If each of the 50 sites were a separate install of WordPress, you would have to update that plugin 50 separate times.

Aggregating content is also another big advantage. It is very easy to share content between your sites in a Multisite network. For example, if you have 50 sites in your network, you could easily aggregate posts from every site to your main blog to showcase your network of sites and content.

The biggest advantage to using Multisite is the speed in which you can launch new sites. With just a few clicks you can create new sites in your network. These sites can share themes, plugins, and even users.

Enabling Multisite

Enabling the Multisite feature of WordPress is a pretty straightforward process. The first step is to add the following line of code to your wp-config.php file:

define( 'WP_ALLOW_MULTISITE', true );

This line of code should be added just above the comment that reads:

/* That's all, stop editing! Happy blogging. */.

Save your wp-config.php file and upload to your server. Now log in to the admin dashboard of WordPress and you’ll notice a new submenu item for Tools ➢ Network Setup, as shown in Figure 10.1.

images

Figure 10.1 Network Setup submenu

The Network Setup screen will vary depending on your current WordPress setup. If your setup allows it, you will choose either Subdomains or Subdirectories for your Multisite setup. You also need to verify that the Server Address, Network Title, and Admin E-mail Address values are correct. These are filled in automatically by WordPress, but you can modify the values if needed. After you have confirmed that the settings are what you want, click the Install button to install Multisite in WordPress.

The final step to enabling Multisite will be presented on the screen; it’s a series of manual changes you need to make to WordPress.

The first step is to add some code to your wp-config.php file. This code defines the base settings for Multisite and will vary depending on your setup. The following is a code example for a Subdirectory install of Multisite under the example.com domain.

define('MULTISITE', true);

define('SUBDOMAIN_INSTALL', false);

define('DOMAIN_CURRENT_SITE', 'example.com');

define('PATH_CURRENT_SITE', '/');

define('SITE_ID_CURRENT_SITE', 1);

define('BLOG_ID_CURRENT_SITE', 1);

The final step is to replace your .htaccess file rules with the new rules provided:

RewriteEngine On

RewriteBase /

RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin

RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]

RewriteCond %{REQUEST_FILENAME} -d

RewriteRule ^ - [L]

RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]

RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]

RewriteRule . index.php [L]

These rules may differ depending on your Multisite setup, so make sure you copy the code provided in the Network Setup screen when enabling Multisite in WordPress.

After making the required changes, you will be required to log back in to WordPress. The easiest way to tell when Multisite is enabled is through the WordPress admin bar. You’ll notice a new menu item named My Sites. When hovering over this menu, the first Submenu link is Network Admin, which is the main admin dashboard for Multisite. The My Sites menu will also list all sites you are a member of in your network, as shown in Figure 10.2. WordPress Multisite is now enabled and ready to use!

images

Figure 10.2 Multisite Network menu

WORKING IN A NETWORK

Now that you know how to enable Multisite in WordPress, it’s important to understand how to manage your network. This section covers the Multisite Network Admin section of WordPress and how to manage a network.

Network Admin

The WordPress Multisite Network Admin is the central hub for all Multisite management of your network. You can access the Network Admin under the My Sites menu in the WordPress admin bar or by visiting http://example.com/wp-admin/network/.

The Network Admin should look very familiar because its layout and style are very similar to the standard WordPress admin dashboard.

Creating and Managing Sites

To view a list of all sites in your Multisite Network, visit the Sites menu. Here you will see every site registered in Multisite, regardless of the status of the site. The list screen gives you some important information, such as the site name, last updated date, registered date, and all users that are members of that site. To edit any site’s settings, click on the site name to bring up the Edit Site screen.

The Edit Site section allows you to edit all settings of a specific site in your network. You’ll notice tabs for each settings section, as shown in Figure 10.3.

images

Figure 10.3 Edit Site section

The Info tab allows you to edit the domain and path of the site. These two settings are not configurable for the main site in your network. You can also change the Registered and Last updated date and timestamps. The final editable item is the Attributes, or site status, setting. Every site in your network can have one of the following five site statuses:

· Public—Site is public if privacy is set to enable search engines.

· Archived—Site has been archived and is not available to the public.

· Spam—Site is considered spam and is not available to the public.

· Deleted—Site is flagged for deletion and is not available to the public.

· Mature—Site is flagged as mature.

The only two statuses that don’t remove the site from public viewing are Public and Mature.

The Users tab allows you to administer what users have access to this site. This section will list all users of the site with their role. You can also add new users to the site. The next section covers users in Multisite in more detail.

The Themes tab allows you to enable or disable themes for the site. Enabling a theme on this screen does not actually activate the theme for the site you are editing, but rather, makes that theme an available option for the site administrator to enable should he choose to do so.

The Settings tab enables you to edit all other settings for the site. There are a lot of options on this screen. As a good rule, if you don’t know what you are changing, you probably shouldn’t change it.

Working with Users and Roles

Users in a Multisite network work differently than in standard WordPress. The major difference is that each site in the network can have a different set of users. Users can also be a member of multiple sites in your network and even have a different user role for each site. For example, you could be an Administrator on site A, but only an Author on site X.

If Allow New Registrations is enabled under the Network Settings menu, visitors can register new user accounts in WordPress. A New User is not automatically a member of every site in your network, but rather the main (first) site in your network. For example, if your network features two sites, a Halloween site and a Christmas site, any visitor who registers would be a member of the Halloween site but not the Christmas site. Of course, you could always add this user to the Christmas site later.

To view all users in your Multisite network, visit the Users menu. Here you will see a list of all users in the network along with their names, e-mail addresses, registered dates, and a list of sites they are members of. If the user is a Super Admin, you will see that information listed next to her username. You can easily add, edit, or delete users from your network in this section.

Themes and Plugins

Multisite handles themes and plugins differently than standard WordPress. All sites in your network can run the same plugins and themes, or they can run a completely different set of plugins and themes. The flexibility of this really showcases the power of Multisite in WordPress.

Themes

To view all themes installed in WordPress, visit the Themes menu. The Network Admin Themes section lists all themes in a list similar to the standard WordPress Plugins section. The major difference is that rather than an Activate link for each theme, you’ll notice aNetwork Enable link instead. Network Enabling any theme listed will make that theme an available option for all sites in your network. This doesn’t actually activate the theme, but rather makes the theme available to site administrators under the Appearance ➢ Themes menu in WordPress. This allows you to control what themes are available for your site administrators to choose from.

Plugins

Plugins work differently from themes in Multisite. Plugins can be Network Activated, which means the plugin will run on every site in your network. If a plugin is not Network Activated, it can still be activated at the site level. This means that you can run plugins on any, or all, sites in your network.

To view all plugins available for use, visit the Plugins menu. Here you’ll see a list of plugins that have been downloaded to WordPress. Clicking the Network Activate link will activate the plugin across every site in your network. If a plugin is not Network Activated, it will be available to activate at the site level under the standard Plugins menu.

NOTE It’s important to verify that a plugin is Multisite-compatible prior to network-enabling the plugin. If the plugin hasn’t been tested on Multisite, or coded properly, there is a chance it could break your network when activated network wide.

Settings

The Settings menu lets you set network-wide settings in Multisite. Here you can enable user account registration and even site creation for your users. Enabling both of these features would allow visitors to register user accounts and even create new sites in your network.

You can also set what file types are allowed for upload, total site upload space, and the max upload file size. If you plan on launching a very large Multisite network, limiting site upload space and max upload size could save you a massive amount of disk space.

By default, the Plugins menu is hidden from site administrators. This allows only Super Admins to activate and deactivate plugins at the site level. If you want to enable the Plugins menu for regular administrators, you can do so under the Menu Settings section.

Domain Mapping

One very common feature for Multisite users is domain mapping. Earlier, you considered the two default site configurations for Multisite: Subdirectory or Subdomain. But what if you want each site in your network to have a unique domain name? There’s a plugin for that! The WordPress MU Domain Mapping plugin (https://wordpress.org/plugins/wordpress-mu-domain-mapping/) allows you to do just that. This plugin makes it very easy to attach a top-level domain to any site in your network. The plugin also works with both Subdirectory and Subdomain setups. For example, instead of two sites like http://example.com/brad and http://example.com/myers, you could have http://brad.com and http://myers.com. All URLs will be served up using the top-level domain you have assigned to your sites.

There have been discussions around rolling domain-mapping functionality into the Core of WordPress, but for now you’ll have to use a plugin to accomplish it.

CODING FOR MULTISITE

When Multisite is enabled in WordPress, you can take advantage of an entirely new set of Multisite-specific functions and APIs in your themes and plugins. Understanding these new features can help you make your themes and plugins Multisite-compatible.

Blog ID

Every site in your Multisite network has a unique ID associated with it. This unique ID is called the Blog ID. Almost every function you work with when writing Multisite-specific code will use this Blog ID. This is how WordPress determines what site you want to work with.

The Blog ID is also used in the database table prefix with each new site you create in your network. When you create new sites in Multisite, WordPress creates additional database tables to store that site’s content and settings. For example, if you create a second site in your network, WordPress will create new tables prefixed like wp_2_posts, where wp_ is the table prefix you defined when installing WordPress, and 2_ is the Blog ID of the new site.

The Blog ID is stored in the global variable $blog_id, as shown here:

<?php

global $blog_id;

echo 'Current Blog ID: ' .$blog_id;

?>

In Multisite, the $blog_id will always be the ID of the current site you are viewing. In standard WordPress, the $blog_id global variable will always be 1.

Common Functions

Some common functions are available when working with Multisite. The most important function when working with Multisite is the is_multisite() function, as shown here:

<?php

if ( is_multisite() ) {

echo 'Multisite is enabled';

}

?>

This function determines whether Multisite is enabled and, if so, returns true. Anytime you plan on using Multisite-specific functions in WordPress, it’s extremely important that you verify that Multisite is actually enabled before doing so. If Multisite is not enabled, and you call a Multisite function, you will receive an error message and the site will break.

Another useful function for retrieving site-specific information is the get_blog_details() function.

<?php get_blog_details( $fields, $getall ); ?>

The function accepts two parameters:

· $fields—Blog ID, a blog name, or an array of fields to query against

· $getall—Whether to retrieve all details

Using this function, you can retrieve general site information for any site specified.

<?php print_r( get_blog_details( 1 ) ); ?>

Running the preceding code example displays the following results:

stdClass Object

(

[blog_id] => 1

[site_id] => 1

[domain] => example.com

[path] => /

[registered] => 2012-10-31 19:01:47

[last_updated] => 2012-10-31 19:01:49

[public] => 1

[archived] => 0

[mature] => 0

[spam] => 0

[deleted] => 0

[lang_id] => 0

[blogname] => Halloween Site

[siteurl] => http://example.com

[post_count] => 420

)

When working in a Multisite network, you may need to retrieve a list of all sites in the network. To do this, you’ll use the wp_get_sites() function. This function will return an array of sites in your network.

<?php

$all_sites = wp_get_sites();

print_r( $all_sites );

The preceding code will return an array of all sites in the network with site-specific information including domain, date registered, and the site status:

Array(

[0] => Array(

[blog_id] => 1

[site_id] => 1

[domain] => example.com

[path] => /

[registered] => 2015-03-31 17:56:46

[last_updated] => 2015-03-31 18:57:19

[public] => 1

[archived] => 0

[mature] => 0

[spam] => 0

[deleted] => 0

[lang_id] => 0

)

[1] => Array(

[blog_id] => 2

[site_id] => 1

[domain] => example.com

[path] => /halloweensite/

[registered] => 2015-03-31 18:07:22

[last_updated] => 2013-03-31 18:13:40

[public] => 1

[archived] => 0

[mature] => 0

[spam] => 0

[deleted] => 0

[lang_id] => 0

)

)

It’s important to note that if you use this function on a large network, which by default is defined as a network with over 10,000 users or sites, this function will return an empty array. Querying for a list of all sites in a network with tens of thousands of sites would be a huge resource hog. You’ll cover detecting large networks later on in this chapter.

Switching and Restoring Sites

One of the main advantages to using WordPress Multisite is how easy it is to aggregate content, and other data, between different sites in your Multisite network.

There are two primary functions you can use to retrieve data from other sites in your network. The first of these is the switch_to_blog() function. This function enables you to switch to any site in your network:

<?php switch_to_blog( $blog_id, $validate ); ?>

The function accepts two parameters:

· $blog_id—The ID of the site you want to switch to.

· $validate—Whether to check if the site exists before proceeding. The default is false.

The second function is restore_current_blog(). This function does exactly what it sounds like: It restores the previous site after a switch_to_blog() function is called. There are no parameters for this function; simply call it after you are done gathering content and data from the site.

Consider the following example that uses these two functions. In this example, you’ll create a custom shortcode to retrieve the latest five posts from a site in your network:

add_shortcode( 'show_network_posts', 'prowp_get_network_posts' );

First, register a new shortcode called show_network_posts using the add_shortcode() function. The new shortcode will accept one parameter, which is the Blog ID you want to display the latest posts from. Next, you’ll create the function to return the latest posts from a site in your network.

function prowp_get_network_posts( $atts ) {

extract( shortcode_atts( array(

'blog_id' => '1'

), $atts ) );

//verify Multisite is enabled

if ( is_multisite() ) {

//switch to blog based on ID

switch_to_blog( absint( $blog_id ) );

//create a custom loop

$recent_posts = new WP_Query();

$recent_posts->query( 'posts_per_page=5' );

$site_posts = '';

//start the custom loop

while ( $recent_posts->have_posts() ) :

$recent_posts->the_post();

//store the recent posts in a variable

$site_posts .= '<p><a href="' . get_permalink() . '">'

. get_the_title() . '</a></p>';

endwhile;

//restore the current site

restore_current_blog();

}

//return the posts

return $site_posts;

}

As always, you need to verify that Multisite is enabled using the is_multisite() function check. Next, use the switch_to_blog() function to switch to the Blog ID passed in through the shortcode. If the user does not set the Blog ID in the shortcode, it will default to Blog ID 1. Now that you’ve switched to the site, you’ll create a custom loop using WP_Query to pull the latest posts from the site. Next, loop through the WP_Query results, storing each post in a variable called $site_posts.

After the loop has completed, you need to run restore_current_blog() to switch back to the previous site you were viewing. If you do not run this function, WordPress stays on Blog ID 10, so any subsequent loops or custom code will assume you are still on Blog ID 10, when in fact you are not. The final step is to return the variable $site_posts, which contain the latest five posts from Blog ID 10.

That’s it! Now you can easily display the most recent blog posts from any site in your network using the shortcode: [show_network_posts blog_id="10"]. Listing 10-1 shows the entire code packaged up in a plugin.

LISTING 10-1: Multisite shortcode example (code file: prowp3-multisite-shortcode.zip)

<?php

/*

Plugin Name: ProWP3 Multsite Shortcode Example

Plugin URI: http://strangework.com/wordpress-plugins

Description: A shortcode to display posts from any site in your network

Version: 1.0

Author: Brad Williams

Author URI: http://strangework.com

License: GPLv2

*/

add_shortcode( 'show_network_posts', 'prowp_get_network_posts' );

function prowp_get_network_posts( $atts ) {

extract( shortcode_atts( array(

'blog_id' => '1'

), $atts ) );

//verify Multisite is enabled

if ( is_multisite() ) {

//switch to blog based on ID

switch_to_blog( absint( $blog_id ) );

//create a custom loop

$recent_posts = new WP_Query();

$recent_posts->query( 'posts_per_page=5' );

$site_posts = '';

//start the custom loop

while ( $recent_posts->have_posts() ) :

$recent_posts->the_post();

//store the recent posts in a variable

$site_posts .= '<p><a href="' . get_permalink() . '">'

. get_the_title() . '</a></p>';

endwhile;

//restore the current site

restore_current_blog();

}

//return the posts

return $site_posts;

}

When switching between sites in a network, you may need to determine if a switch is actually in effect. To do so, you’ll use the ms_is_switched() function. This function returns True if switched and False otherwise.

<?php

if ( ms_is_switched() ) {

//you are in a switched state

}

?>

The switch_to_blog() function is not just limited to site content, but can also retrieve other WordPress data including menus, widgets, sidebars, and more. Basically, any data stored in the content database tables (wp_blogid_tablename) is available when usingswitch_to_blog().

Consider a different example. This time you’ll retrieve a specific menu from a site in your Multisite network.

<?php

switch_to_blog( 10 );

wp_nav_menu( 'Main Menu' );

restore_current_blog();

?>

First run switch_to_blog() to switch to Blog ID 10. Next, use the wp_nav_menu() WordPress function to display a menu named Main Menu from the site. Finally, run restore_current_blog() to reset back to the current site you are viewing. The preceding code will display the Main Menu nav menu from Site ID 10 anywhere you run this code.

It’s important to note that the switch_to_blog() function has the potential to generate very large SQL queries, which could cause performance issues with WordPress. It’s best to cache any data retrieved using this function in a transient, which enables data to be temporarily stored as a cached version. WordPress transients are covered in detail in Chapter 8.

Another important note is that switch_to_blog() only changes the database context; it does not inherit the entire site configuration. This means that a site’s plugins are not included in a switch. If you switch to a site and try to execute a function specific to a plugin that is not enabled, you will receive an error message.

Creating a New Site

You’ve learned how to create new sites in the Network Admin of Multisite, so now you will see how to create new sites via code. To do so, you’ll use the wpmu_create_blog() function.

<?php wpmu_create_blog($domain, $path, $title, $user_id, $meta, $site_id); ?>

This function accepts six parameters:

· $domain—The domain of the new site

· $path—The path of the new site

· $title—The title of the new site

· $user_id—The user ID of the user who will be the site admin

· $meta—Additional meta information

· $site_id—The site ID of the site to be created

Only the first four parameters are required; the last two are optional. The $site_id parameter is only used if you plan to run multiple WordPress Networks inside a single installation of WordPress. If the new site is created successfully, the function will return the newly created Blog ID of the site.

For example, you can build a plugin that uses the wpmu_create_blog() function to create new sites in your Multisite network, as follows:

add_action( 'admin_menu', 'prowp_multisite_create_menu' );

function prowp_multisite_create_menu() {

//create custom top-level menu

add_menu_page( 'Multisite Create Site Page', 'Multisite Create Site',

'manage_options', 'prowp-network-create', 'prowp_multisite_create_sites' );

}

First, you’ll create a new top-level menu called Multisite Create Site. This menu will link to a custom function called prowp_multisite_create_sites(), which will allow you to create sites in the network. Go ahead and create that function as follows:

function prowp_multisite_create_sites() {

//check if multisite is enabled

if ( is_multisite() ) {

Remember to always verify that Multisite is enabled using the is_multisite() function. Next, you’ll add the code to retrieve the submitted form field values and create a new site in Multisite:

//if the form was submitted lets process it

if ( isset( $_POST['create_site'] ) ) {

//check nonce for security

check_admin_referer( 'create-network-site', 'prowp-network-plugin' );

//populate the variables based on form values

$domain = sanitize_text_field( $_POST['domain'] );

$path = sanitize_text_field( $_POST['path'] );

$title = sanitize_text_field( $_POST['title'] );

$user_id = absint( $_POST['user_id'] );

//verify the required values are set

if ( $domain && $path && $title && $user_id ) {

//create the new site in WordPress

$new_site = wpmu_create_blog( $domain, $path, $title, $user_id );

//if successful display a message

if ( $new_site ) {

echo '<div class="updated">New site ' .$new_site

. ' created successfully!</div>';

}

//if required values are not set display an error

} else {

echo '<div class="error">New site could not be created.

Required fields are missing</div>';

}

}

First check if $_POST['create_site'] is set. This field will be set only if the form has been submitted. As with any form, you’ll include a nonce security check. Next you’ll populate the variable values with the data submitted via the form. Notice that you’re using the proper sanitizing functions to verify that the values submitted do not contain HTML and PHP code. You also verify the user_id value is a positive integer using the WordPress absint() function.

Now that the variables are set, you want to verify they each have a value. If you are missing data for any of the four required parameters an error message is displayed. After you’ve verified that the values exist, it’s time to execute the wpmu_create_blog() function to create the new site. If the new site is created successfully, the variable $new_site will contain the new Blog ID of the site.

Now you will build the form for the new site fields using the following:

<div class="wrap">

<h2>Create New Site</h2>

<form method="post">

<?php

//create nonce hidden field for security

wp_nonce_field( 'create-network-site', 'prowp-network-plugin' );

?>

<table class="form-table">

<tr>

<th scope="row"><label for="fname">Domain</label></th>

<td><input maxlength="45" size="25" name="domain"

value="<?php echo esc_attr( DOMAIN_CURRENT_SITE ); ?>" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">Path</label></th>

<td><input maxlength="45" size="10" name="path" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">Title</label></th>

<td><input maxlength="45" size="25" name="title" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">User ID</label></th>

<td><input maxlength="45" size="3" name="user_id" /></td>

</tr>

<tr>

<td>

<input type="submit" name="create_site"

value="Create Site" class="button-primary" />

<input type="submit" name="reset" value="Reset" class="button-secondary" />

</td>

</tr>

</table>

</form>

</div>

This is standard HTML to collect the required field data for creating the new site in Multisite. You can now easily create new sites in your network using the full plugin shown in Listing 10-2.

LISTING 10-2: Create sites in Multisite example (code file: prowp3-multisite-create-site.zip)

<?php

/*

Plugin Name: ProWP3 Create Site Example Plugin

Plugin URI: http://strangework.com/wordpress-plugins

Description: A plugin to demonstrate creating sites in Multisite

Version: 1.0

Author: Brad Williams

Author URI: http://strangework.com

License: GPLv2

*/

add_action( 'admin_menu', 'prowp_multisite_create_menu' );

function prowp_multisite_create_menu() {

//create custom top-level menu

add_menu_page( 'Multisite Create Site Page',

'Multisite Create Site', 'manage_options',

'prowp-network-create', 'prowp_multisite_create_sites' );

}

function prowp_multisite_create_sites() {

//check if multisite is enabled

if ( is_multisite() ) {

//if the form was submitted lets process it

if ( isset( $_POST['create_site'] ) ) {

//check nonce for security

check_admin_referer( 'create-network-site',

'prowp-network-plugin' );

//populate the variables based on form values

$domain = sanitize_text_field( $_POST['domain'] );

$path = sanitize_text_field( $_POST['path'] );

$title = sanitize_text_field( $_POST['title'] );

$user_id = absint( $_POST['user_id'] );

//verify the required values are set

if ( $domain && $path && $title && $user_id ) {

//create the new site in WordPress

$new_site = wpmu_create_blog( $domain, $path,

$title, $user_id );

//if successfully display a message

if ( $new_site ) {

echo '<div class="updated">New site ' . $new_site

. ' created successfully!</div>';

}

//if required values are not set display an error

} else {

echo '<div class="error">New site could not be created.

Required fields are missing</div>';

}

}

?>

<div class="wrap">

<h2>Create New Site</h2>

<form method="post">

<?php

//create nonce hidden field for security

wp_nonce_field( 'create-network-site',

'prowp-network-plugin' );

?>

<table class="form-table">

<tr>

<th scope="row"><label for="fname">Domain</label></th>

<td><input maxlength="45" size="25" name="domain"

value="<?php echo esc_attr( DOMAIN_CURRENT_SITE ); ?>" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">Path</label></th>

<td><input maxlength="45" size="10" name="path" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">Title</label></th>

<td><input maxlength="45" size="25" name="title" /></td>

</tr>

<tr>

<th scope="row"><label for="fname">User ID</label></th>

<td><input maxlength="45" size="3" name="user_id" /></td>

</tr>

<tr>

<td>

<input type="submit" name="create_site"

value="Create Site" class="button-primary" />

<input type="submit" name="reset" value="Reset"

class="button-secondary" />

</td>

</tr>

</table>

</form>

</div>

<?php

} else {

echo '<p>Multisite is not enabled</p>';

}

}

Network Admin Menus

Earlier in this chapter, we covered the Multisite Network Admin section of WordPress. This Dashboard is where all network settings are configured. As in standard WordPress, you can add menus and submenus to the Network Admin screen. To do this, you’ll use the network_admin_menu action hook, as shown here:

add_action( 'network_admin_menu', 'prowp_add_network_settings_menu' );

The network_admin_menu action hook is triggered after the default network admin menu structure is in place. The second parameter is the custom function prowp_add_network_settings_menu(), which will register your new menu.

function prowp_add_network_settings_menu() {

//add settings menu

add_menu_page( 'ProWP3 Options Page', 'ProWP3 Options',

'manage_options', 'prowp-network-settings', 'prowp_network_settings' );

}

As you can see, registering the new menu is exactly the same as registering a standard WordPress menu. In this example, you use the add_menu_page() function to create a new top-level menu in the Network Admin, as shown in Figure 10.4.

images

Figure 10.4 Network Admin top-level menu

Just as easily as you can add a new top-level menu to the Network Admin, you can add submenu items to existing menus. To do this, you’ll use the add_submenu_page() function, as shown here:

add_action( 'network_admin_menu', 'prowp_add_network_settings_menu' );

function prowp_add_network_settings_menu() {

//add settings menu

add_menu_page( 'ProWP3 Options Page', 'ProWP3 Options',

'manage_options', 'prowp-network-settings', 'prowp_network_settings' );

add_submenu_page( 'prowp-network-settings', 'ProWP3 Help Page',

'ProWP3 Help', 'manage_options', 'prowp-network-help',

'prowp_network_help' );

}

This function works exactly as in standard WordPress. The first parameter, settings.php in this case, is the most important. That value tells the function what top-level menu to add your submenu to. In this example, you added a submenu item called ProWP3 Options to the Settings menu in the Network Admin.

The following is a list of file names that you can add submenus to:

· index.php—Add submenu to the Dashboard menu.

· sites.php—Add submenu to the Sites menu

· users.php—Add submenu to the Users menu.

· themes.php—Add submenu to the Themes menu.

· plugins.php—Add submenu to the Plugins menu.

· settings.php—Add submenu to the Settings menu.

· update-core.php—Add submenu to the Updates menu.

As a general rule, it’s best to add your network settings as a submenu of the Settings menu in the Network Admin. This is where most users will look for plugin settings, just like in standard WordPress.

Multisite Options

When storing options in Multisite, it’s important to use the proper functions to store the options in the proper place. The question you should ask yourself is who should control the settings value. If the setting is specific to each site in the network, and can vary between sites, then you should store your options as site options. If the setting should be a network-wide setting that shouldn’t vary between sites, then you should store your options as network options.

Site Options

To store site-specific options in Multisite, you can utilize the *_blog_option() functions. The following is a list of each function:

· add_blog_option()—Creates a new option

· update_blog_option()—Updates an option and creates it if it doesn’t exist

· get_blog_option()—Loads a site option

· delete_blog_option()—Deletes a site option

These functions work almost identically to the standard WordPress option functions; the major difference is that the functions require a $blog_id parameter to be defined, as shown here:

<?php add_blog_option( $blog_id, $key, $value ); ?>

The $key parameter is the option name you want to set and the $value parameter is the value to set for the option.

Retrieving a site option is just as easy. The following example shows you how to use get_blog_option() to retrieve site-specific options for Blog ID 10:

<?php

$blog_id = 10;

echo '<p>Site ID: ' .$blog_id .'</p>';

echo '<p>Site Name: ' .get_blog_option( $blog_id, 'blogname' ) .'</p>';

echo '<p>Site URL: ' .get_blog_option( $blog_id, 'siteurl' ) .'</p>';

?>

Network Options

To store network-wide options in Multisite, you can utilize the *_site_option() functions. The follow list describes each function:

· add_site_option()—Creates a new network option

· update_site_option()—Updates a network option and creates it if it doesn’t exist

· get_site_option()—Loads a network option

· delete_site_option()—Deletes a network option

These functions work almost identically to standard WordPress option functions, but the option values are stored in the wp_sitemeta Multisite database table. You can use these functions to store global Multisite settings that should be the same for all sites in your network.

<?php add_site_option( $key, $value ); ?>

Notice that you do not need to define the Blog ID when adding a network option. Because you are storing a network option, it doesn’t matter what Blog ID the code is being executed from.

If Multisite is not enabled, and your code calls one of the *_site_option() functions, WordPress will fall back to using standard *_option() functions such as add_option().

Network Options Example

Now that you understand how to create and retrieve network options, let’s build a simple network options plugin for Multisite. In this example, you are going to build a plugin to store network wide options. The plugin will degrade gracefully, so if the user is not running Multisite, the options will be stored as standard WordPress options.

The first step in your plugin will be to add the network settings menu.

add_action( 'init', 'prowp_network_settings_menu' );

function prowp_network_settings_menu() {

if ( is_multisite() ) {

//Multisite is enabled so add menu to Network Admin

add_action( 'network_admin_menu', 'prowp_add_network_settings_menu' );

} else {

//Multisite is NOT enabled so add menu to WordPress Admin

add_action( 'admin_menu', 'prowp_add_network_settings_menu' );

}

}

The init action hook is used to call your custom function to register the network options menu. Notice how the is_multisite() function is used in the preceding example. If the user has Multisite enabled, the new menu will be added to the Network Admin of Multisite. If the user does not have Multisite enabled, the menu will be added as a standard WordPress menu. This code is important to preserve compatibility regardless of whether Multisite is enabled or not.

Now that you’ve registered the proper menu action hook, you need to create the custom function to register the new menu.

function prowp_add_network_settings_menu() {

//add settings menu

add_menu_page( 'Network Options Page', 'Network Options',

'manage_options', 'prowp-network-settings', 'prowp_network_settings' );

}

The preceding code uses the add_menu_page() function to create a new top-level menu labeled Network Options. Now that the menu has been created, you need to create the actual settings form.

//generate the settings page

function prowp_network_settings() {

?>

<div class="wrap" >

<div id="icon-options-general" class="icon32"></div>

<h2>Network Settings</h2>

<form method="post">

<?php

//load option values

$network_settings = get_site_option( 'prowp_network_settings' );

$api_key = $network_settings['api_key'];

$holiday = $network_settings['holiday'];

$rage_mode = ( ! empty( $network_settings['rage_mode'] ) )

? $network_settings['rage_mode'] : '';

//create nonce hidden field for security

wp_nonce_field( 'save-network-settings', 'prowp-network-plugin' );

?>

<table class="form-table">

<tr><th scope="row">API Key:</th>

<td><input type="text" name="network_settings[api_key]"

value="<?php echo esc_attr( $api_key ); ?>" /></td>

</tr>

<tr><th scope="row">Network Holiday</th>

<td>

<select name="network_settings[holiday]">

<option value="halloween"

<?php selected( $holiday, 'halloween' ); ?> >

Halloween

</option>

<option value="christmas"

<?php selected( $holiday, 'christmas' ); ?> >

Christmas

</option>

<option value="april_fools"

<?php selected( $holiday, 'april_fools' ); ?> >

April Fools

</option>

</select>

</td>

</tr>

<tr><th scope="row">Rage Mode:</th>

<td><input type="checkbox" name="network_settings[rage_mode]"

<?php checked( $rage_mode, 'on' ); ?> /> Enabled

</td>

</tr>

</table>

<p class="submit">

<input type="submit" class="button-primary"

name="network_settings_save" value="Save Settings" />

</p>

</form>

</div>

<?php

}

You’ll use a standard HTML form to manage the network settings. The options will be stored as an array in a single option, as described in the Plugin Settings section of Chapter 8. The first step is to load any existing setting values. Using the get_site_option()function, you’ll load the prowp_network_settings value, which is your options array, if any exists. Next, set each option value into individual variables. Before you actually create your form, use the wp_nonce_field() function to create a hidden form field nonce for security.

Now it’s time to build the form. The first form field is an API Key, which is a standard text field. The second form field is a select field. Notice how you use the selected() function to determine which option should be selected. The final setting is a check box for Rage Mode. This option uses the checked() function to determine if the option is checked or not. Because you are using a standard HTML form, you’ll need to add a submit button to submit the form values.

Now that your network settings form is set up, you’ll need to create the function to process and save the form data.

add_action( 'admin_init', 'prowp_save_network_settings' );

//save the option values

function prowp_save_network_settings() {

//if network settings are being saved, process it

if ( isset( $_POST['network_settings'] ) ) {

//check nonce for security

check_admin_referer( 'save-network-settings', 'prowp-network-plugin' );

//store option values in a variable

$network_settings = $_POST['network_settings'];

//use array map function to sanitize option values

$network_settings = array_map( 'sanitize_text_field', $network_settings );

//save option values

update_site_option( 'prowp_network_settings', $network_settings );

}

}

You’ll use the admin_init hook for your custom function for saving the form data. The first step is to verify that form values have been posted. If the form wasn’t submitted, there’s nothing for you to process. You’ll do this by verifying that $_POST['network_settings'] is actually set by using the isset() PHP function. Once you’ve verified that there is form data to process, you need to check your nonce using the check_admin_referer() function.

Once the nonce check passes, you’ll store the post data in the $network_settings variable. Because the data that you are processing is user-provided, it’s important to sanitize that data before storing it in the database. In this example, you’ll use the array_map() PHP function, which will send each individual value of the array to any function specified, in this case the sanitize_text_field() WordPress function. Now that your data is properly sanitized, you’ll save the option using the update_site_option() function.

That’s it! You have just built a fully functional network settings section that is fully compatible with standard WordPress. If the user is running Multisite, the menu will show in the Network Admin and the option values will be stored in the wp_sitemeta table. If the user is not running Multisite, the menu will show in the standard WordPress Admin Dashboard and the option values will be stored in the wp_options table.

Listing 10-3 shows the finalized plugin.

LISTING 10-3: Multisite network settings (code file: prowp3-multisite-network-settings.zip)

<?php

/*

Plugin Name: ProWP3 Network Settings Example

Plugin URI: http://strangework.com/wordpress-plugins

Description: This is a plugin demonstrating the Multisite Network WordPress

Settings

Version: 1.0

Author: Brad Williams

Author URI: http://strangework.com

License: GPLv2

*/

add_action( 'init', 'prowp_network_settings_menu' );

function prowp_network_settings_menu() {

if ( is_multisite() ) {

//Multisite is enabled so add menu to Network Admin

add_action( 'network_admin_menu', 'prowp_add_network_settings_menu' );

} else {

//Multisite is NOT enabled so add menu to WordPress Admin

add_action( 'admin_menu', 'prowp_add_network_settings_menu' );

}

}

function prowp_add_network_settings_menu() {

//add settings menu

add_menu_page( 'Network Options Page', 'Network Options',

'manage_options', 'prowp-network-settings',

'prowp_network_settings' );

}

//generate the settings page

function prowp_network_settings() {

?>

<div class="wrap" >

<div id="icon-options-general" class="icon32"></div>

<h2>Network Settings</h2>

<form method="post">

<?php

//load option values

$network_settings =

get_site_option( 'prowp_network_settings' );

$api_key = $network_settings['api_key'];

$holiday = $network_settings['holiday'];

$rage_mode = ( ! empty( $network_settings['rage_mode'] ) )

? $network_settings['rage_mode'] : '';

//create nonce hidden field for security

wp_nonce_field( 'save-network-settings',

'prowp-network-plugin' );

?>

<table class="form-table">

<tr><th scope="row">API Key:</th>

<td><input type="text"

name="network_settings[api_key]"

value="<?php echo esc_attr( $api_key ); ?>" /></td>

</tr>

<tr><th scope="row">Network Holiday</th>

<td>

<select name="network_settings[holiday]">

<option value="halloween" <?php selected( $holiday,

'halloween' ); ?> >Halloween</option>

<option value="christmas" <?php selected( $holiday,

'christmas' ); ?> >Christmas</option>

<option value="april_fools" <?php selected( $holiday,

'april_fools' ); ?> >April Fools</option>

</select>

</td>

</tr>

<tr><th scope="row">Rage Mode:</th>

<td><input type="checkbox"

name="network_settings[rage_mode]"

<?php checked( $rage_mode, 'on' ); ?> /> Enabled</td>

</tr>

</table>

<p class="submit">

<input type="submit" class="button-primary"

name="network_settings_save" value="Save Settings" />

</p>

</form>

</div>

<?php

}

add_action( 'admin_init', 'prowp_save_network_settings' );

//save the option values

function prowp_save_network_settings() {

//if network settings are being saved, process it

if ( isset( $_POST['network_settings'] ) ) {

//check nonce for security

check_admin_referer( 'save-network-settings', 'prowp-network-plugin' );

//store option values in a variable

$network_settings = $_POST['network_settings'];

//use array map function to sanitize option values

$network_settings = array_map( 'sanitize_text_field', $network_settings );

//save option values

update_site_option( 'prowp_network_settings', $network_settings );

}

}

Users in a Network

When working with users in a Multisite network, you should always verify that a user is a member of a specific site. To do this, you’ll use the is_user_member_of_blog() function:

<?php is_user_member_of_blog( $user_id, $blog_id ); ?>

The function accepts two optional parameters. The first parameter is the user ID of the user you want to check. If not set, the function will check the current user. The second parameter is the Blog ID. If this parameter isn’t set, the function defaults to the current site you are on:

<?php

if ( is_user_member_of_blog() ) {

//current user is a member of this site

}

?>

The preceding code example will verify that the user is a member of the current site they are viewing.

Now that you understand how to verify that a user is a member of a site, you can add users to a site with the add_user_to_blog() function:

<?php add_user_to_blog( $blog_id, $user_id, $role ); ?>

The function accepts three parameters:

· $blog_id—The ID of the site you want to add the user to

· $user_id—The ID of the user to add

· $role—The role the user will have on the site

Now build a plugin that automatically adds a logged-in user to any site that the user visits in your Multisite network, as follows:

add_action( 'init', 'prowp_multisite_add_user_to_site' );

First, you’ll use the init action hook to execute your custom function to add users to the site.

function prowp_multisite_add_user_to_site() {

//verify user is logged in before proceeding

if( ! is_user_logged_in() )

return false;

//load current blog ID and user data

global $current_user, $blog_id;

//verify user is not a member of this site

if( ! is_user_member_of_blog() ) {

//add user to this site as a subscriber

add_user_to_blog( $blog_id, $current_user->ID, 'subscriber' );

}

}

The first step is to verify the user is logged in, and if not, exit the function by returning false. Next you’ll call the global $current_user and $blog_id variables. These variables store the data of the current logged-in user and the Blog ID the user is currently viewing. Next, confirm that the user is not a member of the current site using the is_user_member_of_blog() function. The final step is to add the user to the site using the add_user_to_blog() function. In this example you set the role of the user to subscriber, but you could easily change this to any role you’d like.

That’s it! For this plugin to work across your entire network you’ll either need to Network Activate the plugin or upload to the /mu-plugins directory. Either option will force the plugin to run across all sites in your network.

The finalized plugin is shown in Listing 10-4.

LISTING 10-4: Automatically add users to sites in Multisite (code file: prowp3-multisite-add-users.zip)

<?php

/*

Plugin Name: ProWP3 Multisite Auto-Add User to Site

Plugin URI: http://strangework.com/wordpress-plugins

Description: Plugin automatically adds the user to any site they visit

Version: 1.0

Author: Brad Williams

Author URI: http://strangework.com

License: GPLv2

*/

add_action( 'init', 'prowp_multisite_add_user_to_site' );

function prowp_multisite_add_user_to_site() {

//verify user is logged in before proceeding

if( ! is_user_logged_in() )

return false;

//load current blog ID and user data

global $current_user, $blog_id;

//verify user is not a member of this site

if( ! is_user_member_of_blog() ) {

//add user to this site as a subscriber

add_user_to_blog( $blog_id, $current_user->ID, 'subscriber' );

}

}

Now that you understand how to add users to a site, you can remove users from a site. To remove users, you’ll use the remove_user_from_blog() function:

<?php remove_user_from_blog( $user_id, $blog_id, $reassign ); ?>

This function accepts three parameters:

· $user_id—ID of the user you want to remove

· $blog_id—ID of the blog to remove the user from

· $reassign—ID of a user to reassign posts to

The $user_id and $blog_id parameters are required. The $reassign parameter is optional. This parameter should be the ID of the user you want to reassign posts to when removing a user.

NOTE Remember that adding and removing users from a site in Multisite is not actually creating or deleting the user in WordPress, but instead adding or removing them as a member of a specific site.

To retrieve a list of all sites a user belongs to you’ll use the get_blogs_of_user() function. This function returns an array of objects containing the details of each site the user has access to. Here’s an example:

<?php

$user_id = 1;

$user_blogs = get_blogs_of_user( $user_id );

echo 'User '.$user_id.'\'s blogs:<ul>';

foreach ( $user_blogs AS $user_blog ) {

echo '<li>' .$user_blog->blogname .'</li>';

}

echo '</ul>';

?>

The preceding code retrieves the site data for all sites that user ID 1 is a member of. You then loop through the returned array, displaying the blogname value for each site.

Super Admins

Earlier in this chapter, we covered the new user role introduced in Multisite, the Super Admin role. Any user set to the Super Admin role has full control over every site in your Multisite network. Users set to the Super Admin role also have full control over what themes and plugins are available, all users, and network-wide settings.

To retrieve a list of all Super Admins in Multisite you’ll use the get_super_admins() function. This function accepts no parameters and returns an array of all Super Admin usernames in your network. Here’s an example:

<?php

$all_admins = get_super_admins();

print_r( $all_admins );

?>

The preceding code example would return the following array of Super Admins:

Array

(

[0] => admin

[1] => michael_myers

)

You can also check a specific user ID to determine if this user is a Super Admin in your network. To do so, use the is_super_admin() function, as shown here:

<?php

$user_id = 1;

if ( is_super_admin( $user_id ) ) {

echo 'User is a Super Admin';

}

?>

The preceding code example checks if User ID 1 is a Super Admin. The function accepts a $user_id as an optional parameter. If the user ID isn’t passed to the function, it defaults to the current user.

Now that you understand how to check for Super Admins, you can make a user a Super Admin. You can easily assign an existing user to the Super Admin role by using the grant_super_admin() function. This function accepts a single required parameter, which is the user ID you want to add to the Super Admin role.

<?php

$user_id = 34;

grant_super_admin( $user_id );

?>

You can also easily remove a user from the Super Admin role with the revoke_super_admin() function. As in the preceding code, this function accepts a single parameter, which is the user ID you want to remove from the Super Admin role:

<?php

$user_id = 34;

revoke_super_admin( $user_id );

?>

Both of these functions are located in wp-admin/includes/ms.php. This means that these functions are not available on the public side of your website and can only be used on the admin side.

Network Stats

Multisite features various functions to generate stats about your network. The get_blog_count() function returns the total number of sites in your network. To return the total number of users in your network, use the get_user_count() function:

<?php

$site_count = get_blog_count();

$user_count = get_user_count();

echo '<p>Total sites: ' .$site_count .'</p>';

echo '<p>Total users: ' .$user_count .'</p>';

?>

You can also use the get_sitestats() function to retrieve both values at once in an array:

<?php

$network_stats = get_sitestats();

echo '<p>Total sites: ' .$network_stats['blogs'] .'</p>';

echo '<p>Total users: ' .$network_stats['users'] .'</p>';

?>

Large Networks

WordPress Multisite networks can vary in size from a small network of just a few sites, to a very large network with thousands of sites. When working with Multisite, it’s important to always keep this in mind. Writing code that affects all sites in the network may not work as well if the network is substantial in size. WordPress has a function to help determine if a Multisite network is considered to be a large network. The wp_is_large_network() function will check if your Multisite network has more than 10,000 users or more than 10,000 sites, and if so will return True. Let’s look at an example:

<?php

if ( wp_is_large_network() ) {

echo 'Your network is very large!';

}

?>

As you can see, this function is very important and should be used any time you plan on running resource-intensive code. This certainly doesn’t mean you can’t run intensive code on a large network, but you would need to consider caching and optimization techniques to ensure your code runs successfully.

MULTISITE DATABASE SCHEMA

WordPress Multisite features a different database schema from standard WordPress. When enabling Multisite, WordPress creates the necessary tables in your database to support Multisite functionality.

Multisite-Specific Tables

WordPress stores global Multisite settings in centralized tables. These tables are created only when Multisite is enabled and installed, excluding the wp_users and wp_usermeta tables, which exist in standard WordPress.

· wp_blogs—Contains each site created in Multisite.

· wp_blog_versions—Contains the current database version of each site in the network.

· wp_registration_log—A log of all users registered and activated in WordPress.

· wp_signups—Contains users and sites registered using the WordPress registration process.

· wp_site—Contains the primary site’s address information.

· wp_sitecategories—Contains global terms. Only exists if global terms have been enabled in WordPress.

· wp_sitemeta—Contains option data for the network, including Super Admin accounts.

· wp_users—Contains all users registered in WordPress.

· wp_usermeta—Contains all metadata for user accounts in WordPress.

As you have probably noticed, some important WordPress tables are missing. The rest of the tables created for Multisite are site-specific.

Site-Specific Tables

Every site in your network features its own set of site-specific database tables. These tables contain the content and settings specific to that individual site. Remember that these tables are prefixed with the $table_prefix value defined in wp-config.php, followed by the$blog_id and then the table name.

· wp_2_commentmeta

· wp_2_comments

· wp_2_links

· wp_2_options

· wp_2_postmeta

· wp_2_posts

· wp_2_terms

· wp_2_term_relationships

· wp_2_term_taxonomy

Every time you create a new site in your Multisite network, WordPress will create the preceding nine tables in your database for the new site. As you can see, these tables can make your database quickly grow in size. That’s why the only limitation to WordPress Multisite is the server resources available for your network of sites. If your network contains 1,000 sites, your database would have more than 9,000 tables. Obviously a network of this size would not work well on a small, shared hosting account.

In Chapter 6, we covered the importance of using the WordPress database class when querying the database directly. This is especially important in Multisite because the table prefix contains the Blog ID of the site you are viewing. When writing a custom query, you should always prefix the table reference with $wpdb->, which will include the site ID if you are running Multisite. For example, $wpdb->posts would query the wp_2_posts table, assuming you are working on Blog ID 2 in your network.

SUMMARY

WordPress Multisite is an amazing feature of WordPress with limitless possibilities. Now that Multisite is a core WordPress feature, many users are converting their standard WordPress website to a Multisite network to take advantage of the rapid site deployment features and network capabilities. As more and more users are becoming familiar with the power of Multisite, its use is growing at a very rapid pace. When developing for WordPress, it’s very important to think about Multisite and how your code can utilize these powerful Multisite features covered in this chapter. As a WordPress user, it’s also very important to verify the themes and plugins you are using are Multisite compatible.

The next chapter covers WordPress migrations. You’ll learn to understand the content migration process, review various data mapping tools including WP-CLI, and walk through a data migration example.