switch_to_blog()的每个实例之后,您应该调用restore_current_blog()来还原当前(实际上是先前的)博客。

但是,如果您要遍历两个或多个博客并在每个博客上调用switch_to_blog(),是否有理由不在循环结束时不使用其他switch_to_blog()来切换到原始博客,而不是调用每次通过restore_current_blog()。 br />
 $original_blog_id = get_current_blog_id();
 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
 }
 switch_to_blog( $original_blog_id );


评论

现在我明白了,感谢您纠正了我的回答;)我正在修改所有内容。

#1 楼

switch_to_blog()的每个实例之后,您都需要调用restore_current_blog(),否则WP会认为它处于“交换”模式,并可能返回错误的数据。

如果您查看两个函数的源代码,则会看到这些函数将数据推入/弹出到名为$GLOBALS['_wp_switched_stack']的全局变量中。如果您在每个restore_current_blog()之后都没有调用switch_to_blog(),则$GLOBALS['_wp_switched_stack']将为非空。如果$GLOBALS['_wp_switched_stack']是非空的,即使您使用switch_to_blog()切换回原始博客,WP也会认为它处于切换模式。开关模式功能是ms_is_switched(),它会影响wp_upload_dir()。如果wp_upload_dir()认为它处于切换模式,则它可以返回不正确的数据。 wp_upload_dir()为站点构建URL,因此它是非常关键的功能。

这是正确的用法:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog();
 }


评论


谢谢,我还没有机会研究wp_upload_dir()用来生成url的常量和逻辑的内容,但是我想请您相信这确实会导致错误的行为。无论如何,ms_is_switched()的存在意味着我的替代方法导致该函数无法正常运行,并且可能会破坏插件以及核心。谢谢

–斯蒂芬·哈里斯(Stephen Harris)
13年11月17日在22:59

如果是这样,则restore_current_blog()的Codex页面需要更新,因为它说对于多个开关,只需保存当前的$ blog_id,然后使用多个switch_to_blog()调用。

– Pat J
13年11月21日在16:54

#2 楼

如果要运行多个博客,则无需每次都还原以前的博客。唯一增长的是$GLOBALS['_wp_switched_stack'] –一个具有博客ID的数组,没什么好担心的。以前的博客-而不是第一个博客。因此,存储第一个博客ID,并在完成后调用…

switch_to_blog( $first_blog_id ); 
unset ( $GLOBALS['_wp_switched_stack'] );
$GLOBALS['switched'] = false; 

restore_current_blog()。必须重置全局变量,否则您将遇到@ user42826提到的问题。

性能影响巨大。我在具有12个站点的本地安装上运行了一些测试:

$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>';


结果:

12 sites
With restore_current_blog():    0.010648012
Without restore_current_blog(): 0.005203962


每次切换后使用restore_current_blog()会使切换所需的时间加倍。

评论


认为没有任何理由不这样做。感到困惑的是,为什么restore_current_blog()不只是检索以前的博客ID并调用switch_to_blog()-简要查看代码源,似乎有一些代码重复...

–斯蒂芬·哈里斯(Stephen Harris)
13年3月2日在20:52

我不认为直接修改全局变量不是一个好主意,因为您会将代码耦合到Core的内部,这不是面向未来的。最好正确使用API​​。

–伊恩·邓恩
2014年9月29日在17:17

@IanDunn仅作记录:switch_to_blog()是一个非常有限的(损坏的)API。如果WordPress可以解决此问题,则无论如何我们都必须重构代码。 WordPress永远不会放弃其心爱的全球客户。

– fuxia♦
2015年2月2日,0:54

@IanDunn我不认为直接修改全局变量是一个好主意,不要告诉wp核心开发人员;)

– Ejaz
16-2-2在19:14

@ J.D。当然,您需要了解上下文。对于已经切换的状态,您甚至可能必须维护正确的堆栈索引。我可能会寻找避免这种情况的方法。另一方面,这是WordPress,因此可能没有其他方法……

– fuxia♦
16年7月20日在19:28

#3 楼

感谢@toscho回答。 WP队列中的此请求-在此处查看更新。直到WP中已修复,如果有人迫切希望使用标准restore_current_blog(),那么这里是另一种方法(如果我错了,请更正): >
function restore_original_blog_X(){

    if(!empty(($GLOBALS['_wp_switched_stack'][0])){
        $GLOBALS['blog_id']= $GLOBALS['_wp_switched_stack'][0];
        $GLOBALS['_wp_switched_stack'] = array($GLOBALS['_wp_switched_stack'][0]);
        restore_current_blog();
    }

}


,并在完成多个开关时仅执行一次。
(更多:wp-includes / ms-blogs.php)