Wo, wann und wie werden Rewrite-Regeln im Rahmen eines Plugins ordnungsgemäß gelöscht?

10

Ich habe ein seltsames Problem damit, dass Umschreiberegeln nicht richtig geleert werden.

Ich habe versucht, flush_rewrite_rules();und zu verwenden flush_rewrite_rules(true);.

Ich habe auch versucht, $wp_rewritemit $wp_rewrite->flush_rules();und zu globalisieren$wp_rewrite->flush_rules(true);

Keiner von beiden scheint die Umschreiberegeln korrekt zu leeren. Diese Aufrufe leeren tatsächlich die Umschreiberegeln, wenn sie aufgerufen werden. Woher weiß ich das? Verwenden der Lösung zum Debuggen zum Löschen von Umschreiberegeln .

Derzeit habe ich Regeln für die Aktivierung und Deaktivierung von Plugins neu geschrieben. Keine Probleme da.

Ich habe eine Seite mit den Einstellungen für die Plugin-Verwaltung, auf der Benutzer das Plugin konfigurieren können. Einige der Einstellungen passen die Permalink-Struktur an, sodass die Umschreiberegeln auf der Seite "Einstellungen speichern" der Plugin-Verwaltungseinstellungen gelöscht werden müssen. (Verwendet den Standard update_option();) zum Speichern von Einstellungen.

Ich möchte darauf hinweisen, dass abhängig von den angegebenen Einstellungen benutzerdefinierte Beitragstypen erstellt werden, die den benutzerdefinierten Einstellungen entsprechen. Daher müssen die Umschreiberegeln sofort nach dem Speichern der Einstellungen gelöscht werden. Hier funktionieren die Dinge nicht richtig.

Die obige Link-Lösung zum Debuggen von Umschreiberegeln, die von bereitgestellt @toschowird, zeigt an, dass Tonnen von Umschreiberegeln gelöscht werden. Wenn Sie jedoch das einzelne Element des benutzerdefinierten Beitragstyps oder sogar das Archiv des benutzerdefinierten Beitragstyps besuchen, wird jedes als 404-Fehler zurückgegeben.

Der benutzerdefinierte Beitragstyp wird korrekt und entsprechend registriert. Ich weiß mit Sicherheit, dass das nicht das Problem ist.

Sofort nach dem Einfügen der Plugin-Verwaltungsseite Einstellungen speichern. Die benutzerdefinierten Beitragstypen werden erstellt, die Permalink-Struktur wird angepasst und es wird versucht, alle Umschreiberegeln zu löschen.

Die benutzerdefinierten Beitragstypen werden dann immer geladen und initwie gewohnt geladen .

Aus irgendeinem Grund werden die Umschreiberegeln nicht richtig geleert, da, wie ich bereits sagte, beim Besuch einzelner oder archivierter Abschnitte des benutzerdefinierten Beitragstyps 404 Fehler zurückgegeben werden.

Der seltsame Teil: Wenn ich nur die Einstellungsseite für Administrationspermalinks besuche und dann zum Front-End zurückkehre, um entweder einzelne oder Archivabschnitte des benutzerdefinierten Beitragstyps anzuzeigen, funktionieren sie auf magische Weise wie erwartet.

Was macht diese Einstellungsseite für Administrationspermalinks, die ich nicht mache, damit die Umschreiberegeln ordnungsgemäß geleert werden können und meine nicht?

Ich meine, als temporäre Lösung leite ich den Benutzer nach dem Speichern der Seite mit den Einstellungen für die Plugin-Verwaltung auf die Seite mit den Einstellungen für Administrationspermalinks um, aber dies ist keine ideale Lösung. Ich würde es vorziehen, wenn die Umschreiberegeln im Code meines Plugins ordnungsgemäß gelöscht werden.

Gibt es einen bestimmten Punkt in WordPress, an dem das Löschen der Umschreiberegeln nicht mehr ALLE Regeln löscht?

admin_menu - Die Seite mit den Plugin-Einstellungen wurde zur WordPress-Administration hinzugefügt.

add_options_page() - Die Seite mit den Plugin-Einstellungen wurde im Menü Einstellungen hinzugefügt.

Die Einstellungsseite wird im Rückruf für gerendert add_options_page(). Hier wird auch das $_POSTAktualisieren der Plugin-Einstellungen und das Löschen von Umschreiberegeln verarbeitet.

Da dies bereits eine lange Frage ist, wäre ich bereit, Codeblöcke (falls dies hilfreich ist) in einem externen Link bereitzustellen, um die Erstellung einer gültigen Antwort zu unterstützen.

Michael Ecklund
quelle
1
Es hört sich so an, als ob Sie die Reihenfolge der Dinge falsch verstanden haben. Es ist schwer zu sagen, ohne Code zu sehen. Auf der Permalinks-Administrationsseite wird nur aufgerufen flush_rewrite_rules, wodurch die rewrite_rulesOption gelöscht und neu generiert wird. Sie können die Datei öffnen wp-admin/options-permalinks.phpund sehen, wo dies geschieht. Da durch diesen Vorgang nur die gesamte Option gelöscht wird, können Regeln nicht teilweise gelöscht werden.
Milo
@ Milo Ich denke du hast recht. Ich habe eine Klasse, die geladen wird und initdie die Beitragstypen registriert. Ich dachte mir, die Seiteneinstellungen würden gespeichert und die Seite würde neu geladen ... und dann den initHook erneut ausgelöst, um die erforderlichen Beitragstypen zu registrieren. Also dachte ich, dass die Beitragstypen bereits geladen sein würden, und alles, was ich tun musste, war, die Option zu aktualisieren und dann die Umschreiberegeln von meiner Plugin-Einstellungsseite zu löschen. Ich werde eine Antwort veröffentlichen, wie ich eine Lösung gefunden habe.
Michael Ecklund
Nur eine Warnung flush_rewrite_rules () in meinem Plugin war Teil des Problems für mich. Ich habe den PHP-Hook gelöscht und die Permalinks nur manuell aktualisiert, und meine CPT 404-Fehler sind verschwunden.
Myol

Antworten:

4

Der beste Ort, um Umschreiberegeln zu löschen, ist die Aktivierung / Deaktivierung des Plugins.

function myplugin_activate() {
    // register taxonomies/post types here
    flush_rewrite_rules();
}

register_activation_hook( __FILE__, 'myplugin_activate' );

function myplugin_deactivate() {
    flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );

Siehe den Codex-Artikel

Entschuldigung im Voraus, ich habe Ihre Frage nicht vollständig beantwortet, daher ist dies eine Art Antwort auf den Ausstecher.

Helgatheviking
quelle
1
Vielen Dank für Ihren Vorschlag, aber ich bin mir dessen bewusst. Das Problem betrifft nicht die Aktivierung / Deaktivierung von Plugins. Dies hat damit zu tun, dass Benutzer die Einstellungen auf das bereits aktive Plugin ändern, wodurch die Umschreiberegeln angepasst werden und ein Flush erforderlich ist.
Michael Ecklund
1
Ich dachte, das könnte der Fall sein, aber ich war ziemlich müde, als ich Ihre Frage las. Die Lösung von ialocin sieht vielversprechend aus. Ich hoffe, Sie haben es geschafft.
Helgatheviking
4

Schwer zu sagen, was falsch ist, ohne Ihren Code zu sehen. Nach dem Speichern einiger Einstellungen ist es jedoch praktisch, sich admin_initwie unten gezeigt anzuschließen, um Ihre Umschreiberegeln zu löschen.

Code:

add_action('admin_init', 'wpse_123401_plugin_settings_flush_rewrite');
function wpse_123401_plugin_settings_flush_rewrite() {
    if ( get_option('plugin_settings_have_changed') == true ) {
        flush_rewrite_rules();
        update_option('plugin_settings_have_changed', false);
    }
}


Sie müssen die Option an einer Stelle auf Ihrer Einstellungsseite oder genau an einer Stelle festlegen, an der die Einstellungen gespeichert werden. Es ist schlecht, es ohne die Option zu tun, da Sie die Regeln nicht jedes Mal löschen möchten.


Hinweis: ungetestet

Nicolai
quelle
2
Oder könnten Sie vielleicht einen Übergang verwenden? Aber definitiv +1, wenn die Regeln nicht bei jedem admin_init gelöscht werden.
Helgatheviking
Sie haben natürlich Recht mit Transienten. Ich glaube, ich habe mich *_option()aufgrund der Einstellungsseite dafür entschieden . @helgatheviking
Nicolai
Das war sehr hilfreich. Ich hatte eine ähnliche Situation wie Michael. Am Ende habe ich Helgas Vorschlag zur Verwendung eines Transienten aufgenommen und ihn in der Validierungsfunktion für die Einstellungen festgelegt. Am Ende musste ich den Transienten nach dem Leeren auf false setzen, sonst wurde er bei jedem Laden der Administrationsseite weiter geleert, bis der Transient abgelaufen war. Die funktionale Verwendung einer Option oder eines Transienten war also dieselbe. Ich denke, vorübergehend könnte schön sein, nur um die Optionstabelle ein wenig sauberer zu halten. Aber ein kleiner Punkt.
MatthewLee
Der Unterschied ist in der Tat gering, insbesondere wenn die Transienten permanent sind und nicht ablaufen, aber natürlich haben Transienten andere Fähigkeiten, Vorteile, die schön zu haben sind. @ MatthewLee
Nicolai
3

Ich hatte eine Klassendatei für Beitragstypen, die dafür verantwortlich war, die Optionseinstellungen des Plugins zu lesen und die erforderlichen benutzerdefinierten Beitragstypen basierend auf den benutzerdefinierten Einstellungen zu erstellen.

Diese Klassendatei für Post-Typen wurde in den Hook geladen init.

Ich dachte mir, ich müsste dann nur die Plugin-Einstellungen aktualisieren und dann die Umschreiberegeln löschen. Da die Post-Typ-Klasse bereits basierend auf den Plugin-Einstellungen geladen wurde. Bei Administrationsseiten werden sie jedoch NACH dem initHook geladen .

Die Beitragstypen wurden nie registriert, da die Einstellungen noch nicht festgelegt wurden. Die Registrierungsklasse für Posttypen wurde vorzeitig beendet, ohne dass Posttypen registriert wurden.

Die Lösung war:

  1. Aktualisieren Sie die Plugin-Einstellungen.
  2. Laden Sie die Klassendatei für Post-Typen NUR einmal hier, damit die neuen Umschreiberegeln erstellt werden.
  3. Löschen Sie die Umschreiberegeln.

(Zuvor ... fehlte Schritt 2 - Wie oben erwähnt ...)

Von nun an werden Post-Typen in den initHook geladen und es werden bereits Einstellungen festgelegt, sodass Post-Typen erstellt und mit den entsprechenden Umschreiberegeln gepaart werden können.

Aus irgendeinem Grund musste ich einen JavaScript-Aufruf hinzufügen, um zur aktuellen Seite umzuleiten, nachdem ich die obigen drei Schritte ausgeführt hatte.

Ich musste auch einen Anruf flush_rewrite_rules();auf der Seite mit den Administrationseinstellungen des Plugins hinzufügen .

Um sicherzustellen, dass alles gespült wird ...

Schritt 1) ​​Navigieren Sie zur Seite mit den Administrationseinstellungen des Plugins. - Erstspülung.

Schritt 2) Aktualisieren Sie die Plugin-Einstellungen. - Zweite Spülung.

Schritt 3) Seite leitet zur Einstellungsseite des Plugins weiter. Verursachen der ... Dritte und letzte Spülung (wie erste Spülung - Wird automatisch ausgeführt, wenn die Einstellungsseite des Plugins besucht wird)

Ich sage nicht, dass dies eine praktische Lösung ist, aber es hat bei mir funktioniert. Sehr seltsames Problem und hat höchstwahrscheinlich mit meiner Codierungsinfrastruktur zu tun.

Michael Ecklund
quelle
1

@ tazo-todua das hat auch bei mir funktioniert wenn ich multisite benutze.

add_action( 'wpmu_new_blog', 'set_my_permalink_structure', 11, 2 );

function set_my_permalink_structure( $blog_id ) {

    switch_to_blog( $blog_id );

    global $wp_rewrite;
    $wp_rewrite->set_permalink_structure( '/%postname%/' );
    $wp_rewrite->flush_rules();
    $wp_rewrite->init();

    restore_current_blog();
}
stillatmylinux
quelle
0

MEINE gefundene LÖSUNG WAR:

global $wp_rewrite; $wp_rewrite->flush_rules(); $wp_rewrite->init();
T.Todua
quelle
0

Ich hatte genau das gleiche Problem. In meinem Plugin habe ich Beitragstypen, die dynamisch erstellt werden. Sie können daher register_post_type()während des Hooks nicht über eine statische Methode registriert werden activation_hookund sind daher noch nicht aktiv, wenn flush_rewrite_rules()sie während dieses Hooks ausgeführt werden (was normalerweise die empfohlene Methode zum Löschen von Umschreiberegeln ist).

Die sauberste Lösung, die ich am Ende finden konnte, bestand darin, die Umschreiberegeln nach der Registrierung der Post-Typen zu leeren, aber natürlich nur, wenn eine solche Spülung tatsächlich erforderlich war (weil der Vorgang langsam ist). In meinem Fall habe ich tatsächlich mehrere benutzerdefinierte Beitragstypen, die von einer einzelnen Basisklasse erben. Daher war es wünschenswert, den Code zu implementieren, der das Löschen dort durchführt.

Ob eine Spülung erforderlich ist, kann anhand der Ausgabe von get_option( 'rewrite_rules' ):

class MyPostTypeClass {

public final function register_as_custom_post_type() {
    ...   //do all the setup of your post type here     
    $args = array(
                  ... //populate the other arguments as you see fit
                  'rewrite' => array('slug' => 'slug-of-your-post-type')
                 );
    register_post_type('post-type-name-of-your-post-type', $args );

    $rewrite_rules_must_be_fluhed = true;
    foreach( get_option( 'rewrite_rules' ) as $key => $rule)
        if(strpos($key, $args['rewrite']['slug'] ) === 0)
        {
            $rewrite_rules_must_be_fluhed = false;
            break;
        }
    if($rewrite_rules_must_be_fluhed)
        flush_rewrite_rules(true);
}
}

Nachteile:

  • Bezieht sich in gewissem Maße auf die genauen Umschreiberegeln, die WP während generiert register_post_type().
  • Das Überprüfen, ob während jedes Seitenladens ein Leeren erforderlich ist, verursacht ebenfalls einen gewissen Overhead.

Vorteile:

  • Vollständig in der Klasse gekapselt, die den Beitragstyp darstellt.
  • Löscht die Umschreiberegeln nur, wenn dies wirklich erforderlich ist.

Verwenden Sie diese Option nur, wenn Sie Ihren Beitragstyp nicht in einer statischen Funktion registrieren können, die sowohl während als auch während initdes activation_hook!

Die Abhängigkeit davon, wie die während des register_post_type()Aussehens erzeugten Umschreiberegeln aussehen, kann verringert werden, indem der Test if(strpos($key, $args['rewrite']['slug'] ) === 0)durch etwas Ausgefeilteres ersetzt wird, dh durch einen regulären Ausdruck.

Cgogolin
quelle