Wordpress - restore_current_blog() vs switch_to_blog()
After every instance of switch_to_blog()
you need to call restore_current_blog()
otherwise WP will think it is in a "switched" mode and can potentially return incorrect data.
If you view the source code for both functions you will see those functions push/pop data into a global called $GLOBALS['_wp_switched_stack']
. If you do not call restore_current_blog()
after every switch_to_blog()
, $GLOBALS['_wp_switched_stack']
will be non-empty. If $GLOBALS['_wp_switched_stack']
is non-empty WP thinks it is in a switched mode, even if you switched back to the original blog using switch_to_blog()
. The switched mode function is ms_is_switched()
and it affects wp_upload_dir()
. If wp_upload_dir()
thinks it is in a switched mode, it can return data that is incorrect. wp_upload_dir()
builds URLs for the site, so it is a very critical function.
This is the correct use:
foreach( $blog_ids as $blog_id ){
switch_to_blog( $blog_id );
//Do stuff
restore_current_blog();
}
If you want to run over multiple blogs there is no need to restore the previous blog each time. The only thing that grows is $GLOBALS['_wp_switched_stack']
– an array with blog IDs, nothing to worry about.
But keep in mind, restore_current_blog()
will not work ( ! ! ! ) anymore after the second switch, because it uses the previous blog – which is not the first blog then. So store the first blog ID, and call …
switch_to_blog( $first_blog_id );
unset ( $GLOBALS['_wp_switched_stack'] );
$GLOBALS['switched'] = false;
… instead of restore_current_blog()
when you are done. The global variables must be reset, or you will run into the issues mentioned by @user42826.
The performance impact is huge. I’ve run some tests on a local installation with 12 sites:
$sites = wp_get_sites();
print '<pre>' . count( $sites ) . " sites\n";
timer_start();
print 'With restore_current_blog(): ';
foreach ( $sites as $site ) {
switch_to_blog( $site[ 'blog_id' ] );
restore_current_blog();
}
timer_stop( 1, 9 );
print "\nWithout restore_current_blog(): ";
timer_start();
$current_site = get_current_blog_id();
foreach ( $sites as $site ) {
switch_to_blog( $site[ 'blog_id' ] );
}
switch_to_blog( $current_site );
$GLOBALS['_wp_switched_stack'] = array();
$GLOBALS['switched'] = FALSE;
timer_stop( 1, 9 );
print '</pre>';
Result:
12 sites
With restore_current_blog(): 0.010648012
Without restore_current_blog(): 0.005203962
Using restore_current_blog()
after each switch doubles the time that is needed just for switching.