restore_current_blog () vs switch_to_blog ()

23

Après chaque instance, switch_to_blog()vous devez appeler restore_current_blog()pour restaurer le blog actuel (en fait, précédent).

Mais si vous parcourez deux blogs ou plus et que vous appelez switch_to_blog()chacun d'eux, y a-t-il une raison de ne pas utiliser un autre switch_to_blog()à la fin de la boucle pour basculer vers le blog d'origine plutôt que d'appeler restore_current_blog()à chaque passage.

Par exemple

Pourquoi pas:

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

au lieu de:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog_id();
 }
Stephen Harris
la source
Maintenant je comprends cela, merci d'avoir corrigé ma réponse;) Je révise tout.
brasofilo

Réponses:

19

Après chaque instance, switch_to_blog()vous devez appeler, restore_current_blog()sinon WP pensera qu'il est en mode "commuté" et peut potentiellement renvoyer des données incorrectes.

Si vous affichez le code source pour les deux fonctions, vous verrez ces fonctions pousser / pop les données dans un global appelé $GLOBALS['_wp_switched_stack']. Si vous n'appelez pas restore_current_blog()après chaque switch_to_blog(), $GLOBALS['_wp_switched_stack']sera non vide. Si $GLOBALS['_wp_switched_stack']est non vide, WP pense qu'il est en mode commuté, même si vous êtes revenu au blog d'origine en utilisant switch_to_blog(). La fonction de mode commuté est ms_is_switched()et elle affecte wp_upload_dir(). Si wp_upload_dir()pense qu'il est en mode commuté, il peut renvoyer des données incorrectes. wp_upload_dir()crée des URL pour le site, c'est donc une fonction très critique.

C'est l'utilisation correcte:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog();
 }
user42826
la source
Merci, je n'ai pas eu la chance de travailler à travers la soupe de constantes et de logique qui wp_upload_dir()utilise pour générer des URL, mais je vais croire que cela entraîne effectivement un comportement buggé. Dans tous les cas, l'existence de ms_is_switched()moyens mon approche alternative a pour conséquence que la fonction ne se comporte pas comme prévu et pourrait casser les plug-ins ainsi que le noyau. Merci
Stephen Harris
1
Si cela est vrai, la page du Codex a restore_current_blog()besoin d'une mise à jour, car elle indique que pour plusieurs commutateurs, il suffit d'enregistrer le courant $blog_idet d'utiliser plusieurs switch_to_blog()appels.
Pat J
16

Si vous souhaitez parcourir plusieurs blogs, il n'est pas nécessaire de restaurer le blog précédent à chaque fois. La seule chose qui grandit est $GLOBALS['_wp_switched_stack']- un tableau avec des ID de blog, rien à craindre.

Mais gardez à l'esprit, restore_current_blog() ne fonctionnera plus (!!!) Après le deuxième changement, car il utilise le blog précédent - qui n'est pas le premier blog à ce moment-là. Alors stockez le premier ID de blog et appelez…

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

… Au lieu de restore_current_blog()quand vous avez terminé. Les variables globales doivent être réinitialisées, sinon vous rencontrerez les problèmes mentionnés par @ user42826.

L'impact sur les performances est énorme. J'ai effectué quelques tests sur une installation locale avec 12 sites:

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

Résultat:

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

L'utilisation restore_current_blog()après chaque commutateur double le temps nécessaire à la commutation.

fuxia
la source
Je pensais qu'il n'y avait aucune raison de ne pas le faire. Je restore_current_blog()ne savais pas pourquoi ne pas simplement retrouver l'ID et l'appel du blog précédent switch_to_blog()- un bref aperçu de la source du code et il semble qu'il y ait un peu de duplication de code ...
Stephen Harris
3
Je ne pense pas que la modification directe des globaux soit une bonne idée, car vous associez votre code aux internes de Core, ce qui n'est pas à l'épreuve du temps. Il vaut mieux utiliser l'API correctement.
Ian Dunn
2
@IanDunn Juste pour mémoire: switch_to_blog()est une API très limitée (cassée) de toute façon. Si WordPress résout ce problème , nous devons quand même refactoriser notre code. Et WordPress ne renoncera jamais à ses bien-aimés mondiaux.
fuxia
2
@IanDunn I don't think modifying the globals directly is a good idea, ne le dites pas aux développeurs de base wp;)
Ejaz
1
@JD Bien sûr, vous devez être sensible au contexte. Dans le cas d'un état déjà commuté, vous devrez peut-être même maintenir l'index correct de la pile. Je chercherais probablement un moyen d'éviter cela. D'un autre côté, c'est WordPress, donc il n'y a peut-être pas d'autre moyen…
fuxia
1

Merci à la réponse @toscho. Cette demande en file d'attente de WP - voir les mises à jour ici . Jusqu'à ce que cela soit corrigé dans WP, si quelqu'un veut désespérément utiliser la norme restore_current_blog(), alors voici une autre méthode (veuillez corriger si je me trompe):

faites votre fonction, c.-à-d.

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

}

et exécutez une seule fois lorsque vous avez terminé vos commutateurs multiples. (plus: wp-includes / ms-blogs.php )

T.Todua
la source