restore_current_blog () vs switch_to_blog ()

23

Después de cada instancia switch_to_blog(), debe llamar restore_current_blog()para restaurar el blog actual (en realidad, anterior).

Pero si está pasando por dos o más blogs y está llamando switch_to_blog()a cada uno, ¿hay alguna razón para no usar uno adicional switch_to_blog()al final del ciclo para cambiar al blog original en lugar de llamar restore_current_blog()a cada pase?

P.ej

Por qué no:

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

en lugar de:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog_id();
 }
Stephen Harris
fuente
Ahora entiendo esto, gracias por corregir esa respuesta mía;) Estoy revisando todo.
brasofilo

Respuestas:

19

Después de cada instancia en la switch_to_blog()que necesite llamar, de lo restore_current_blog()contrario, WP pensará que está en modo "conmutado" y puede devolver datos incorrectos.

Si ve el código fuente de ambas funciones, verá esas funciones de inserción / extracción de datos en una llamada global $GLOBALS['_wp_switched_stack']. Si no llama restore_current_blog()después de cada switch_to_blog(), $GLOBALS['_wp_switched_stack']no estará vacío. Si $GLOBALS['_wp_switched_stack']no está vacío, WP cree que está en modo conmutado, incluso si ha vuelto a utilizar el blog original switch_to_blog(). La función de modo conmutado es ms_is_switched()y afecta wp_upload_dir(). Si wp_upload_dir()cree que está en modo conmutado, puede devolver datos incorrectos. wp_upload_dir()crea URL para el sitio, por lo que es una función muy crítica.

Este es el uso correcto:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog();
 }
usuario42826
fuente
Gracias, no he tenido la oportunidad de trabajar a través de la sopa de constantes y lógica que se wp_upload_dir()emplea para generar URL, pero tomaré su palabra de que esto realmente resulta en un comportamiento defectuoso. En cualquier caso, la existencia de ms_is_switched()significa que mi enfoque alternativo da como resultado que la función no se comporte como se esperaba y podría romper los complementos y el núcleo. Gracias
Stephen Harris
1
Si esto es cierto, entonces la página del Codex restore_current_blog()necesita una actualización, ya que dice que para varios conmutadores, uno solo necesita guardar el actual $blog_idy luego usar múltiples switch_to_blog()llamadas.
Pat J
16

Si desea ejecutar varios blogs, no es necesario restaurar el blog anterior cada vez. Lo único que crece es $GLOBALS['_wp_switched_stack']: una matriz con ID de blog, nada de qué preocuparse.

Pero tenga en cuenta que restore_current_blog() ya no funcionará (!!!) Después del segundo cambio, porque utiliza el blog anterior, que no es el primer blog en ese momento. Así que guarde la primera ID de blog y llame ...

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

... en lugar de restore_current_blog()cuando hayas terminado. Las variables globales deben restablecerse, o se encontrará con los problemas mencionados por @ user42826.

El impacto en el rendimiento es enorme. He realizado algunas pruebas en una instalación local con 12 sitios:

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

Resultado:

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

El uso restore_current_blog()después de cada cambio duplica el tiempo que se necesita solo para cambiar.

fuxia
fuente
Pensé que no había ninguna razón para no hacerlo. Fue confundido por qué restore_current_blog()no acaba de retrive el ID de llamada blog anterior y switch_to_blog()- un breve vistazo al código fuente y parece que hay un poco de duplicación de código ...
Stephen Harris
3
No creo que modificar directamente los globales sea una buena idea, porque estás acoplando tu código a los componentes internos de Core, lo que no es a prueba de futuro. Es mejor usar la API correctamente.
Ian Dunn
2
@IanDunn Solo para el registro: switch_to_blog()es una API muy limitada (rota) de todos modos. Si WordPress alguna vez corrige eso , tenemos que refactorizar nuestro código de todos modos. Y WordPress nunca renunciará a sus queridos globales.
fuxia
2
@IanDunn I don't think modifying the globals directly is a good idea, no se lo digas a los desarrolladores principales de wp;)
Ejaz
1
@JD Por supuesto, debes tener en cuenta el contexto. En el caso de un estado ya cambiado, es posible que incluso deba mantener el índice correcto de la pila. Probablemente buscaría una manera de evitar eso. Por otro lado, esto es WordPress, por lo que podría no haber otra manera ...
fuxia
1

Gracias a @toscho respuesta. Esta solicitud en la cola de WP: consulte las actualizaciones aquí . Hasta que se solucione en WP, si alguien quiere desesperadamente usar el estándar restore_current_blog(), entonces aquí hay otro método (corríjalo si estoy equivocado):

hacer su función, es decir

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();
    }

}

y ejecutar solo una vez cuando termine sus múltiples interruptores. (más: wp-includes / ms-blogs.php )

T.Todua
fuente