restore_current_blog () vs switch_to_blog ()

23

Nach jeder Instanz von switch_to_blog()sollten Sie aufrufen restore_current_blog(), um das aktuelle (tatsächlich vorherige) Blog wiederherzustellen.

Wenn Sie jedoch zwei oder mehr Blogs durchlaufen und jeweils aufrufen switch_to_blog(), gibt es einen Grund , am Ende der Schleife kein zusätzliches zu verwenden switch_to_blog(), um zum ursprünglichen Blog zu wechseln, anstatt restore_current_blog()bei jedem Durchgang einen Aufruf zu tätigen.

Z.B

Warum nicht:

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

anstatt:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog_id();
 }
Stephen Harris
quelle
Jetzt verstehe ich das, danke, dass du meine Antwort korrigiert hast;) Ich überarbeite alles.
Brasofilo

Antworten:

19

Nach jeder Instanz, die switch_to_blog()Sie sonst aufrufen müssen , restore_current_blog()glaubt WP, dass es sich in einem "geschalteten" Modus befindet und möglicherweise falsche Daten zurückgeben kann.

Wenn Sie den Quellcode für beide Funktionen anzeigen, sehen Sie, dass diese Funktionen Daten in ein globales Verzeichnis mit dem Namen push / pop verschieben $GLOBALS['_wp_switched_stack']. Wenn Sie nicht restore_current_blog()nach jedem anrufen switch_to_blog(), $GLOBALS['_wp_switched_stack']wird nicht leer sein. Wenn $GLOBALS['_wp_switched_stack']es nicht leer ist, denkt WP, dass es sich um einen umgeschalteten Modus handelt, auch wenn Sie mit zum ursprünglichen Blog zurückgeschaltet haben switch_to_blog(). Die Schaltfunktion ist ms_is_switched()und wirkt sich aus wp_upload_dir(). Wenn es wp_upload_dir()denkt, dass es sich in einem geschalteten Modus befindet, kann es falsche Daten zurückgeben. wp_upload_dir()Erstellt URLs für die Site, daher ist dies eine sehr wichtige Funktion.

Dies ist die richtige Verwendung:

 foreach( $blog_ids as $blog_id ){
    switch_to_blog( $blog_id );
    //Do stuff
    restore_current_blog();
 }
user42826
quelle
Vielen Dank, ich hatte keine Gelegenheit, die Konstantensuppe und die Logik wp_upload_dir()zu durcharbeiten, die zum Generieren von URLs verwendet werden, aber ich nehme Ihr Wort, dass dies tatsächlich zu fehlerhaftem Verhalten führt. In jedem Fall führt das Vorhandensein von ms_is_switched()Mitteln, die mein alternativer Ansatz verwendet, dazu, dass sich die Funktion nicht wie erwartet verhält und sowohl Plug-Ins als auch den Kern beschädigen kann. Vielen Dank
Stephen Harris
1
Wenn dies zutrifft, muss die Codex-Seite für restore_current_blog()aktualisiert werden, da für mehrere Switches nur die aktuelle gespeichert $blog_idund dann mehrere switch_to_blog()Aufrufe verwendet werden müssen.
Pat J
16

Wenn Sie mehrere Blogs durchsuchen möchten, müssen Sie das vorherige Blog nicht jedes Mal wiederherstellen. Das einzige, was wächst, ist $GLOBALS['_wp_switched_stack']ein Array mit Blog-IDs, über das Sie sich keine Sorgen machen müssen.

Aber denken Sie daran, restore_current_blog() wird nach dem zweiten Wechsel nicht mehr funktionieren (!!!) , Da es das vorherige Blog verwendet - das ist dann nicht das erste Blog. Speichern Sie also die erste Blog-ID und rufen Sie an…

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

... anstatt restore_current_blog()wenn Sie fertig sind. Die globalen Variablen müssen zurückgesetzt werden, andernfalls treten die von @ user42826 genannten Probleme auf.

Die Auswirkungen auf die Leistung sind enorm. Ich habe einige Tests auf einer lokalen Installation mit 12 Standorten durchgeführt:

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

Ergebnis:

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

Durch die Verwendung restore_current_blog()nach jedem Schalter wird die Zeit verdoppelt, die nur zum Umschalten benötigt wird.

fuxia
quelle
Dachte, es gab keinen Grund, es nicht zu tun. War verwirrt, warum restore_current_blog()nicht einfach die vorherige Blog-ID abgerufen und aufgerufen wurde switch_to_blog()- ein kurzer Blick auf die Code-Quelle und es scheint, als gäbe es ein bisschen Code-Duplikation ...
Stephen Harris
3
Ich halte es nicht für eine gute Idee, die Globals direkt zu ändern, da Sie Ihren Code mit den Internals von Core koppeln, was nicht zukunftssicher ist. Es ist besser, die API richtig zu verwenden.
Ian Dunn
2
@IanDunn Nur fürs Protokoll: Ist switch_to_blog()sowieso eine sehr eingeschränkte (kaputte) API. Wenn WordPress das jemals behebt , müssen wir unseren Code trotzdem überarbeiten. Und WordPress wird niemals seine geliebten Globals aufgeben.
fuxia
2
@ IanDunn I don't think modifying the globals directly is a good idea, sag das nicht wp Core-Entwickler;)
Ejaz
1
@JD Natürlich müssen Sie kontextsensitiv sein. Im Falle eines bereits geschalteten Zustands müssen Sie möglicherweise sogar den korrekten Index des Stapels beibehalten. Ich würde wahrscheinlich nach einem Weg suchen, das zu vermeiden. Auf der anderen Seite ist dies WordPress, es könnte also keinen anderen Weg geben…
fuxia
1

Danke an @toscho Antwort. Diese Anfrage in der Warteschlange von WP - siehe Updates hier . Bis das in WP behoben ist, wenn jemand dringend Standard verwenden möchte restore_current_blog(), dann ist hier eine andere Methode (bitte korrigieren, wenn ich falsch liege):

machen Sie Ihre Funktion, dh

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

}

und nur einmal ausführen, wenn Sie Ihre mehreren Schalter beendet haben. (mehr: wp-includes / ms-blogs.php )

T.Todua
quelle