Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

When I call switch_to_blog() with a blog id, I don’t know if that blog actually exists. The functions returns always TRUE.

Here is my problem:

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

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

Real world use case

I am the lead developer of Multilingual Press. When a user translates a post, she gets a screen like this:

enter image description here

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.

share|improve this question
    
How about $wpdb->blogid; and the hook wp_insert_post_data ? –  JMau Mar 18 at 0:49
    
@JMau get_post() is just a read. There can be a long pause between the last save and the next edit screen reload. –  toscho Mar 18 at 0:54
4  
A per-request cached SQL query for blog_id in wp_blogs table (where deleted = 0)? –  G. M. Mar 18 at 1:32
1  
@G.M. SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND public = '1' AND archived = '0' AND spam = '0' AND deleted = '0' –  kaiser Mar 18 at 2:58
    
@toscho Thinking out loud... There's wp_cache_switch_to_blog(), but it only helps with persistant cache, not the default on page WP thing. Anyway, to me it's not really clear where you want to check the blog existence: When someone deletes a blog or when someone tries to write the translated post that points to a different blog (powering the same content in another language)? –  kaiser Mar 18 at 3:02

1 Answer 1

up vote 6 down vote accepted

@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." );
share|improve this answer
    
why $wpdb->get_results + wp_list_pluck instead of only (int) $wpdb->get_var? however +1, and I think that something similar should be in core switch_to_blog... –  G. M. Mar 18 at 14:07
    
@G.M. get_var() returns just one result. I have used get_col() now, and I made sure an empty result is not fetched again. –  toscho Mar 18 at 20:21
    
Ah ok... I better read the query now, you get all the blog ids for a specific site id, at first read I thougt you get only one blog id at time (the one passed to function)... sure the array way is better. I'm sorry isn't possible +1 again :) –  G. M. Mar 18 at 20:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.