Beware when using switch_to_blog()
Published: â Leave a comment Last update:
switch_to_blog is a handy function to switch sites (âblogsâ) in a multisite. However, beware that you might have problems with certain data in such context switches.
What does it actually do?
What it actually does, it switches the site ID for $wpdb, the database object in WordPress, and switches the cache. This is practically it. This way, it allows you to perform database/cache changes for any given site.
Why is this a problem?
There are so much more functions that rely on data regarding the current site â and by current I mean the site before the switch took place. As an example, get_template_directory_uri relies on the constant WP_CONTENT_URL. This usually returns the URL to the wp-content folder. For a site in https://www.example.com, it returns https://www.example.com/wp-content.
If you now switch the blog to another site, e.g. https://www.example.com/new-site/, WP_CONTENT_URL still returns https://www.example.com/wp-content, since itâs defined before. Also, you cannot overwrite it, since itâs a constant.
Also, global data like the global $post object or similar wonât be touched by switch_to_blog, so make sure to update them as needed.
How to fix the problems?
Depending on what data youâre using, there are different possibilities to fix them. Sometimes, there might no solution at all.
get_template_directory_uri
For get_template_directory_uri, you can use the filter theme_root_uri to overwrite it and replace the site used before a switch_to_blog with the site afterwards.
The code looks then like this:
$main_site_url = \site_url();
\switch_to_blog( $site_id );
\add_filter( 'theme_root_uri', static function( string $theme_root_uri, string $site_url ) use ( $main_site_url ): string {
return \str_replace( $main_site_url, $site_url, $theme_root_uri );
}, 10, 2 );
\restore_current_blog();
Code language: PHP (php)
Basically, it uses the generated $theme_root_uri and replaces the site URL from the main site (which is the site you were at before running switch_to_blog) with the site URL from the current site after switching it.
Getting/changing post metadata
Another problem could be to switch a site to retrieve certain posts. If you do and you need metadata from these posts using get_post_meta, make sure to switch the site again to retrieve them or retrieve them before restoring the old site, since it wonât find this data otherwise in the restored site.
Restoring current site is important
Whenever you switch the site, WordPress remembers the site you were at before. To switch to the previous site, always make sure to run restore_current_blog after youâre done with your adjustments to the other site.
If you donât do it or donât do it as often as youâve used switch_to_blog, you will experience odd issues with getting values of the wrong site in the end.
Example
$site_ids = [ 2, 3, 4 ];
echo 'Current site: ' . \get_current_blog_id() . \PHP_EOL;
foreach ( $site_ids as $site_id ) {
\switch_to_blog( $site_id );
echo 'Switched to ' . $site_id . \PHP_EOL;
echo \get_current_blog_id() . \PHP_EOL;
}
\restore_current_blog();
echo 'Restored site to: ' . \get_current_blog_id() . \PHP_EOL;
Code language: PHP (php)
Here, weâre switching the site three times, first to the site with ID 2, then with 3 and then with 4. Weâre always using get_current_blog_id to verify the switch did happen.
If youâre unfamiliar with how switch_to_blog works, you might think that restore_current_blog in the end resets the site ID to 1 again, which it was at the beginning. However, the output is this:
Current site: 1
Switched to 2
2
Switched to 3
3
Switched to 4
4
Restored site to: 3
As you can see, restore_current_blog always only returns to the last used site before switch_to_blog has been executed. To fix the function above, restore_current_blog has always also run inside the foreach loop:
$site_ids = [ 2, 3, 4 ];
echo 'Current site: ' . \get_current_blog_id() . \PHP_EOL;
foreach ( $site_ids as $site_id ) {
\switch_to_blog( $site_id );
echo 'Switched to ' . $site_id . \PHP_EOL;
echo \get_current_blog_id() . \PHP_EOL;
\restore_current_blog();
}
echo 'Restored site to: ' . \get_current_blog_id() . \PHP_EOL;
Code language: PHP (php)
Which then creates the following output:
Current site: 1
Switched to 2
2
Switched to 3
3
Switched to 4
4
Restored site to: 1
Conclusion
The main purpose of switch_to_blog is to allow database/cache changes of a certain site when being in the context of another site. If using file system related functions or a global context (e.g. the global $post object), beware that they might still be in the original context from the site before switching.
Reposts
Likes