How can I trust switch_to_blog()?

When I call switch_to_blog() with a blog id, I don’t know whether that blog actually exists. The function returns always true.

Test case:

switch_to_blog(PHP_INT_MAX);
$post = get_post(1);
restore_current_blog();

This will result in database errors that are exposed to the user. How can I prevent that?

Real-world use case

I was the lead developer of MultilingualPress. When a user translates a post, she gets a screen like this:

Now the following can happen:

  1. She saves the post successfully and continues translating the post.
  2. Another user, a network admin, deletes the German blog while she is writing.
  3. She hits save again and gets database errors.

I want to avoid that scenario. How can I check quickly if the target blog exists? I call switch_to_blog() very often in multiple different classes, so it has to be fast.

Topic switch-to-blog multisite database Wordpress

Category Web


if( get_blog_details( [ 'blog_id' => $blogIdToTest ] ) ) {
 // Exists
} else {
 // Dont exists
}

You could use get_site with the id of the blog to archieve this.

From the docs (https://developer.wordpress.org/reference/functions/get_site/): returns (WP_Site|null) The site object or null if not found.

So all you have to do is something like this:

// Replace PHP_INT_MAX with the var which holds the site id you want to check against
if(!is_null(get_site(PHP_INT_MAX)){
//do stuff if site exists
}
else{
// do stuff if the site doesn't exists (anymore)
}

@G.M.’s idea to cache the check has lead me to the following helper function. I’ve put it into the global namespace to have it available everywhere.

The function doesn’t say anything about the blog status, just if it exists and is not marked as deleted. The database query is very fast (0.0001 seconds) and runs just one query per site id, no matter how often the function is called.

if ( ! function_exists( 'blog_exists' ) ) {

    /**
     * Checks if a blog exists and is not marked as deleted.
     *
     * @link   http://wordpress.stackexchange.com/q/138300/73
     * @param  int $blog_id
     * @param  int $site_id
     * @return bool
     */
    function blog_exists( $blog_id, $site_id = 0 ) {

        global $wpdb;
        static $cache = array ();

        $site_id = (int) $site_id;

        if ( 0 === $site_id )
            $site_id = get_current_site()->id;

        if ( empty ( $cache ) or empty ( $cache[ $site_id ] ) ) {

            if ( wp_is_large_network() ) // we do not test large sites.
                return TRUE;

            $query = "SELECT `blog_id` FROM $wpdb->blogs
                    WHERE site_id = $site_id AND deleted = 0";

            $result = $wpdb->get_col( $query );

            // Make sure the array is always filled with something.
            if ( empty ( $result ) )
                $cache[ $site_id ] = array ( 'do not check again' );
            else
                $cache[ $site_id ] = $result;
        }

        return in_array( $blog_id, $cache[ $site_id ] );
    }
}

Usage

if ( ! blog_exists( $blog_id ) )
    return new WP_Error( '410', "The blog with the id $blog_id has vanished." );

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.