wppaste
WordPress

restore_current_blog(): bool

Since
MU (3.0.0)
Source
wp-includes/ms-blogs.php:563

Reverses the site context set by the most recent switch_to_blog() call, popping WordPress back to whichever blog it was on beforehand. It resets the $wpdb table prefix, the current blog ID, and the object cache group for that prior site, and fires the switch_blog action so plugins can react to the change. Pair it one-to-one with switch_to_blog(), since an unbalanced stack leaves table queries and cached values pointed at the wrong site.

Restores the current blog, after calling switch_to_blog().

Compatibility

WordPress
since MU (3.0.0)
PHP
7.4–8.6-dev
  • 6.7.7
  • 6.8.8
  • 6.9.7
  • 7.0.4
  • 7.1.0

Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.

Return value

bool
True on success, false if we're already on the current blog.

Code examples

Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.

Undo a switch_to_blog() call after creating a post on another site

On a multisite network, temporarily jump into a second site to publish a post, then hand control back to whichever site the request started on.

$sites = get_sites( array( 'number' => 2 ) );
$target_blog_id = null;
foreach ( $sites as $site ) {
	if ( (int) $site->blog_id !== get_current_blog_id() ) {
		$target_blog_id = (int) $site->blog_id;
		break;
	}
}

if ( ! $target_blog_id ) {
	echo esc_html( 'No secondary site found to switch into.' );
} else {
	switch_to_blog( $target_blog_id );

	$new_post_id = wp_insert_post( array(
		'post_title'   => 'Cross-posted from the main site',
		'post_content' => 'This copy lives on the branch office site.',
		'post_status'  => 'publish',
	) );

	echo esc_html( sprintf( 'Created post %d on blog %d.', $new_post_id, get_current_blog_id() ) );

	$restored = restore_current_blog();

	echo esc_html( sprintf( ' restore_current_blog() returned %s, current blog is now %d.', $restored ? 'true' : 'false', get_current_blog_id() ) );
}

switch_to_blog() and restore_current_blog() only exist on a multisite install, since they live in code that is loaded solely when is_multisite() is true.

See what restore_current_blog() returns with and without a prior switch

Call the function on its own and then again right after switch_to_blog() to compare the two return values in the same request.

$stack_before = empty( $GLOBALS['_wp_switched_stack'] ) ? 'empty' : 'not empty';
$result_without_switch = restore_current_blog();

switch_to_blog( get_current_blog_id() );
$result_with_switch = restore_current_blog();

echo esc_html( sprintf(
	'Switch stack was %s. Restoring with nothing to undo returned %s. Restoring after switching to the same blog returned %s.',
	$stack_before,
	$result_without_switch ? 'true' : 'false',
	$result_with_switch ? 'true' : 'false'
) );

Switching to the site you are already on still pushes an entry onto the stack, so the second restore still returns true even though nothing about $wpdb actually changes.

Common problems and fixes · 3

Why does restore_current_blog() return false?

The function checks $GLOBALS['_wp_switched_stack'] first and returns false immediately if that array is empty, which means there is no matching switch_to_blog() call left to undo.

Why is $wpdb still querying the site I switched away from?

Each switch_to_blog() call pushes a blog ID onto $GLOBALS['_wp_switched_stack'], and restore_current_blog() only pops one entry per call. If switch_to_blog() was called more times than restore_current_blog(), the stack still has entries and $GLOBALS['switched'] stays true.

Why doesn't the object cache reset when I restore right after switching to the same blog?

When the popped blog ID equals the current blog ID, the source fires the switch_blog action and returns true without calling $wpdb->set_blog_id() or wp_cache_switch_to_blog(), since nothing about the site context actually changed.

Alternatives and related functions

switch_to_blog
When you need to move site context to a different blog in the first place, since restore_current_blog() only undoes that call.
ms_is_switched
When you just need to check whether the site context is currently switched without popping the switch stack.
get_current_blog_id
When you only need the ID of whichever site is active right now rather than reverting to a previous one.

Performance profile

How much work a call to restore_current_blog() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.

Cost class
Light

Only touches the object cache, via wp_cache_switch_to_blog().

Scaling
Constant

No loop in the body: the same number of instructions runs whatever you pass in.

Instructions
4–36

Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 48.

Plugin surface
1 hook

Third-party callbacks on 'switch_blog' run inside this call, and their cost is not bounded by anything here.

Called by
37

37 places in core call this, so the cost is paid more often than your own code shows.

What it touches

  • hookthird-party callbacksdo_action()called directly
  • cacheobject cachewp_cache_switch_to_blog()called directly

What one call costs · 3 distinct outcomes

One number would be a lie: the work depends on which branch runs. These are every distinct cost restore_current_blog() can have, taken from its control-flow graph on PHP 8.5.

WhenInstructionsCalls it makes
empty($value)4none
!empty($value) && $new_blog_id === false24array_pop(), get_current_blog_id(), do_action()
!empty($value) && $new_blog_id !== false36array_pop(), get_current_blog_id(), ->set_blog_id(), ->get_blog_prefix(), wp_cache_switch_to_blog(), do_action()

Across PHP versions

PHPCompiledExecutedBranchesNotes
8.6-dev484–362
8.5484–362
8.4484–362
8.3484–362
8.2484–362
8.1484–3628 fewer instructions than PHP 7.4
7.4565–422

An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.

Hooks and filters fired · 2

2 hooks fire while restore_current_blog() runs, in this order:

  1. do_action( switch_blog )actionline 575 (+12 into the body)

    Fires when the blog is switched.

  2. do_action( switch_blog )actionline 590 (+27 into the body)

    Fires when the blog is switched.

Uses · 3

  • get_current_blog_id()Retrieves the current site ID.
  • do_action()Calls the callback functions that have been added to an action hook.
  • wp_cache_switch_to_blog()Used when switch_to_blog() and restore_current_blog() are called, but only when a persistent object cache drop-in plugin has omitted the wp_cache_switch_to_blog() function that was introduced in 3.5.0.

Used by · 37

Show all 37

Source code

function restore_current_blog() {	global $wpdb; 	if ( empty( $GLOBALS['_wp_switched_stack'] ) ) {		return false;	} 	$new_blog_id  = array_pop( $GLOBALS['_wp_switched_stack'] );	$prev_blog_id = get_current_blog_id(); 	if ( $new_blog_id === $prev_blog_id ) {		/** This filter is documented in wp-includes/ms-blogs.php */		do_action( 'switch_blog', $new_blog_id, $prev_blog_id, 'restore' ); 		// If we still have items in the switched stack, consider ourselves still 'switched'.		$GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] ); 		return true;	} 	$wpdb->set_blog_id( $new_blog_id );	$GLOBALS['blog_id']      = $new_blog_id;	$GLOBALS['table_prefix'] = $wpdb->get_blog_prefix(); 	wp_cache_switch_to_blog( $new_blog_id ); 	/** This filter is documented in wp-includes/ms-blogs.php */	do_action( 'switch_blog', $new_blog_id, $prev_blog_id, 'restore' ); 	// If we still have items in the switched stack, consider ourselves still 'switched'.	$GLOBALS['switched'] = ! empty( $GLOBALS['_wp_switched_stack'] ); 	return true;}

Changelog

Introduced in MU (3.0.0). Unchanged from 6.7.7 through 7.1.0.

  1. 6.7.7
  2. 6.8.8
  3. 6.9.7
  4. 7.0.4
  5. 7.1.0

Signature, return type and hooks compared across 5 parsed releases.

About this page

Parsed data
Generated from the wordpress-develop 7.1.0 tag, from src/wp-includes/ms-blogs.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it.
Corrections
Something wrong on this page? Report it and it gets fixed in the next regeneration.