restore_current_blog () против switch_to_blog ()

23

После каждого экземпляра switch_to_blog()вы должны позвонить, restore_current_blog()чтобы восстановить текущий (фактически, предыдущий) блог.

Но если вы просматриваете два или более блогов и звоните switch_to_blog() в каждый из них, есть ли причина не использовать дополнительный switch_to_blog()в конце цикла для переключения на исходный блог, а не звонить restore_current_blog()при каждом проходе.

Например

Почему бы нет:

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

вместо того:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog_id();
 }
Стивен Харрис
источник
Теперь я понимаю это, спасибо за исправление моего ответа;) Я все пересматриваю.
Brasofilo

Ответы:

19

После каждого случая 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']поле не пустое, WP думает, что оно находится в режиме переключения, даже если вы вернулись в исходный блог, используя switch_to_blog(). Переключаемая функция режима есть 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();
 }
user42826
источник
Спасибо, у меня не было возможности проработать суп из констант и логики, которые wp_upload_dir()используются для генерации URL-адресов, но я верю, что это действительно приводит к ошибочному поведению. В любом случае, наличие ms_is_switched()средств в моем альтернативном подходе приводит к тому, что функция работает не так, как ожидалось, и может сломать как плагины, так и ядро. Спасибо
Стивен Харрис
1
Если это так, то страница Кодекса для restore_current_blog()нуждается в обновлении, поскольку там говорится, что для нескольких коммутаторов нужно только сохранить текущий $blog_idи затем использовать несколько switch_to_blog()вызовов.
Пэт Дж
16

Если вы хотите работать с несколькими блогами, нет необходимости каждый раз восстанавливать предыдущий блог. Единственное, что растет $GLOBALS['_wp_switched_stack']- массив с идентификаторами блогов, не о чем беспокоиться.

Но имейте в виду, restore_current_blog() больше не будет работать (!!!) После второго переключения, потому что он использует предыдущий блог - который не является первым блогом тогда. Так что храните первый идентификатор блога и звоните ...

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()не просто восстановил предыдущий идентификатор блога и позвонил switch_to_blog()- краткий взгляд на источник кода, и кажется, что есть немного дублирования кода ...
Стивен Харрис
3
Я не думаю, что изменение глобальных переменных напрямую является хорошей идеей, потому что вы связываете свой код с внутренними компонентами Core, что не является перспективой на будущее. Лучше правильно использовать API.
Ян Данн,
2
@IanDunn Просто для справки: switch_to_blog()это очень ограниченный (сломанный) API в любом случае. Если WordPress когда-нибудь исправит это , мы все равно должны будем реорганизовать наш код. И WordPress никогда не откажется от своих любимых глобалов.
Fuxia
2
@IanDunn I don't think modifying the globals directly is a good idea, не говорите об этом разработчикам ядра wp;)
Ejaz
1
@JD Конечно, тебе нужно знать контекст. В случае уже переключенного состояния вам, возможно, придется даже поддерживать правильный индекс стека. Я, вероятно, искал бы способ избежать этого. С другой стороны, это WordPress, так что другого пути быть не может…
fuxia
1

Спасибо @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 )

T.Todua
источник