Dove, quando e come eseguire correttamente il flush delle regole di riscrittura all'interno di un plugin

15 nov 2013, 19:20:41
Visualizzazioni: 25.7K
Voti: 16

Ho un problema particolare con le regole di riscrittura che non vengono aggiornate correttamente.

Ho provato a utilizzare flush_rewrite_rules(); e flush_rewrite_rules(true);.

Ho anche provato a globalizzare $wp_rewrite usando $wp_rewrite->flush_rules(); e $wp_rewrite->flush_rules(true);

Nessuno dei due metodi sembra aggiornare correttamente le regole di riscrittura. Quelle chiamate stanno effettivamente eseguendo il flush delle regole quando vengono chiamate. Come lo so? Usando la soluzione per il debug del flush delle regole di riscrittura.

Attualmente, ho il flush delle regole di riscrittura all'attivazione e alla disattivazione del plugin. Nessun problema fin qui.

Ho una pagina di amministrazione delle impostazioni del plugin per permettere agli utenti di configurarlo. Alcune impostazioni modificano la struttura dei permalink, quindi è necessario eseguire il flush delle regole di riscrittura quando si salvano le impostazioni nella pagina di amministrazione del plugin. (Usa il normale update_option(); per salvare le impostazioni).

Vorrei notare che in base alle impostazioni specificate, vengono creati custom post type che corrispondono alle impostazioni specificate dall'utente. Quindi le regole di riscrittura devono essere aggiornate immediatamente dopo il salvataggio delle impostazioni. È qui che le cose non funzionano correttamente.

La soluzione di debug delle regole di riscrittura fornita da @toscho mostra che sta aggiornando molte regole di riscrittura. Tuttavia, quando si visita un elemento singolo del custom post type, o anche l'archivio del custom post type, entrambi restituiscono errori 404.

Il custom post type è registrato correttamente e in modo appropriato. So per certo che non è questo il problema.

Immediatamente dopo il salvataggio delle impostazioni nella pagina di amministrazione del plugin, i custom post type vengono creati, la struttura dei permalink viene modificata e si tenta di aggiornare tutte le regole di riscrittura.

I custom post type vengono poi caricati sempre e caricati su init come di norma.

Per qualche motivo, le regole di riscrittura non vengono aggiornate correttamente, perché come ho detto prima, visitando le sezioni singole o di archivio del custom post type si ottengono errori 404.

Ora la parte strana: se tutto quello che faccio è semplicemente visitare la pagina delle impostazioni dei permalink nell'amministrazione, e poi torno al frontend per visualizzare le sezioni singole o di archivio del custom post type, magicamente funzionano come previsto.

Cosa fa quella pagina delle impostazioni dei permalink nell'amministrazione che io non sto facendo che permette alle regole di riscrittura di aggiornarsi correttamente mentre le mie no?

Come soluzione temporanea, sto reindirizzando l'utente alla pagina delle impostazioni dei permalink dopo aver salvato la pagina delle impostazioni del plugin, ma questa non è una soluzione ideale. Preferirei che le regole di riscrittura si aggiornassero correttamente all'interno del codice del mio plugin.

C'è un certo punto in WordPress in cui l'aggiornamento delle regole di riscrittura smette di aggiornare TUTTE le regole?

admin_menu - La pagina delle impostazioni del plugin viene aggiunta all'amministrazione di WordPress.

add_options_page() - La pagina delle impostazioni del plugin viene aggiunta sotto il menu Impostazioni.

La pagina delle impostazioni viene renderizzata nella callback per add_options_page(). Qui è anche dove viene elaborato $_POST per aggiornare le impostazioni del plugin e aggiornare le regole di riscrittura.

Dato che questa è già una domanda lunga, sarei disposto a fornire blocchi di codice (se può aiutare) in un link esterno per aiutare a produrre una risposta valida.

3
Commenti

Sembra che forse hai sbagliato l'ordine delle operazioni, è difficile dirlo senza vedere del codice. La pagina di amministrazione dei permalink chiama semplicemente flush_rewrite_rules, che elimina l'opzione rewrite_rules e la rigenera, puoi aprire il file wp-admin/options-permalinks.php e vedere dove ciò accade. Poiché questa operazione elimina completamente l'opzione, non è possibile effettuare un flush parziale delle regole.

Milo Milo
15 nov 2013 20:27:18

@Milo Penso che tu abbia ragione. Ho una classe che viene caricata su init e che registra i post type. Pensavo che le impostazioni della pagina venissero salvate, e la pagina si ricaricasse... quindi attivando di nuovo l'hook init per registrare i post type necessari. Quindi pensavo che i post type fossero già caricati, e tutto ciò che dovevo fare era aggiornare l'opzione, poi eseguire il flush delle regole di riscrittura dalla pagina delle impostazioni del mio plugin. Posterò una risposta con la soluzione che ho trovato.

Michael Ecklund Michael Ecklund
15 nov 2013 21:21:56

Attenzione: flush_rewrite_rules() nel mio plugin si è rivelato parte del problema. Ho eliminato l'hook PHP e alla fine ho aggiornato manualmente i permalink, facendo così scomparire gli errori 404 dei miei CPT.

myol myol
20 ott 2014 11:38:33
Tutte le risposte alla domanda 8
2

Il posto migliore per eseguire il flush delle regole di riscrittura è durante l'attivazione/disattivazione del plugin.

function myplugin_activate() {
    // registra qui le tassonomie/tipi di post
    flush_rewrite_rules();
}

register_activation_hook( __FILE__, 'myplugin_activate' );

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

Vedi l'articolo sul codex

Mi scuso in anticipo, non ho letto completamente la tua domanda, quindi questa è una risposta un po' generica.

15 nov 2013 19:37:09
Commenti

Grazie per il suggerimento, ma ne sono già a conoscenza. Il problema non riguarda l'attivazione/disattivazione del plugin. Ha a che fare con gli utenti che modificano le impostazioni del plugin già attivo, il che comporta la regolazione delle rewrite rules, richiedendo quindi un flush.

Michael Ecklund Michael Ecklund
15 nov 2013 21:17:10

Pensavo potesse essere il caso, ma ero piuttosto stanco quando leggevo la tua domanda. La soluzione di ialocin sembra promettente, spero tu l'abbia risolta.

helgatheviking helgatheviking
17 nov 2013 02:22:41
4

Difficile capire cosa non va senza vedere il tuo codice. Ma dopo aver salvato alcune impostazioni, è buona pratica agganciarsi a admin_init come mostrato di seguito per ripulire le regole di riscrittura.

Codice:

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


Devi impostare l'opzione da qualche parte nella tua pagina delle impostazioni o, per essere precisi, nel processo di salvataggio delle impostazioni. Farlo senza l'opzione non è consigliabile, perché non vorrai ripulire le regole ogni volta.


Nota: non testato

15 nov 2013 20:47:37
Commenti

Oppure potresti usare un transient magari? Ma sicuramente +1 per non flushare le regole ad ogni admin_init.

helgatheviking helgatheviking
17 nov 2013 02:23:11

Hai ovviamente ragione riguardo al transient, credo che ho optato per *_option() a causa della pagina delle impostazioni. @helgatheviking

Nicolai Grossherr Nicolai Grossherr
28 nov 2013 00:11:18

Questo è stato molto utile. Avevo una situazione simile a Michael. Alla fine ho incorporato il suggerimento di helga sull'uso di un transient e l'ho impostato nella funzione di validazione per le impostazioni. Ho finito per dover impostare il transient a false dopo il flush altrimenti continuava a fare il flush ad ogni caricamento della pagina admin fino alla scadenza del transient. Quindi funzionalmente usare un'opzione o un transient era la stessa cosa. Immagino che il transient possa essere utile solo per mantenere la tabella delle opzioni un po' più pulita. Ma un punto minore.

MatthewLee MatthewLee
15 feb 2014 19:59:35

La differenza è davvero minima, specialmente se i transient sono permanenti e non scadono, ma ovviamente i transient offrono altre capacità e vantaggi che sono utili da avere. @MatthewLee

Nicolai Grossherr Nicolai Grossherr
15 feb 2014 21:34:22
0

Avevo un file di classe per i tipi di post che era responsabile di leggere le impostazioni delle opzioni del plugin e creare i necessari tipi di post personalizzati in base alle impostazioni specificate dall'utente.

Questo file di classe per i tipi di post veniva caricato sull'hook init.

Pensavo che tutto ciò che avrei dovuto fare fosse aggiornare le impostazioni del plugin e poi svuotare le regole di riscrittura. Poiché la classe dei tipi di post era già caricata in base alle impostazioni del plugin. Ma con le pagine di amministrazione, queste vengono caricate DOPO l'hook init.

I tipi di post non sono mai stati effettivamente registrati, perché le impostazioni non erano ancora state impostate. La classe di registrazione dei tipi di post terminava prematuramente senza che nessun tipo di post fosse registrato.

La soluzione era:

  1. Aggiornare le impostazioni del plugin.
  2. Caricare il file della classe dei tipi di post SOLO una volta qui in modo che le nuove regole di riscrittura vengano create.
  3. Svuotare le regole di riscrittura.

(In precedenza... il passaggio 2 mancava -- Come accennato sopra...)

D'ora in poi, i tipi di post verranno caricati sull'hook init e avranno già le impostazioni specificate, consentendo la creazione dei tipi di post e l'abbinamento con le appropriate regole di riscrittura.

Per qualche motivo, ho dovuto aggiungere una chiamata JavaScript per reindirizzare alla pagina corrente, dopo aver eseguito i tre passaggi sopra.

Ho anche dovuto aggiungere una chiamata a flush_rewrite_rules(); nella pagina delle impostazioni di amministrazione del plugin.

Quindi, per garantire che tutto venga svuotato...

Passaggio 1) Navigare verso la pagina delle impostazioni di amministrazione del plugin. -- Svuotamento iniziale.

Passaggio 2) Aggiornare le impostazioni del plugin. -- Secondo svuotamento.

Passaggio 3) La pagina si reindirizza alla pagina delle impostazioni del plugin. Causando il... Terzo e ultimo svuotamento (lo stesso dello svuotamento iniziale -- Eseguito automaticamente quando si visita la pagina delle impostazioni del plugin)

Non sto dicendo che questa sia una soluzione pratica, ma ha funzionato per me. Problema molto strano e molto probabilmente ha a che fare con la mia infrastruttura di codifica.

15 nov 2013 21:38:08
0

Avevo esattamente lo stesso problema. Nel mio plugin, ho dei post type che vengono creati dinamicamente. Di conseguenza, non possono essere registrati tramite register_post_type() in un metodo statico durante l'activation_hook e quindi non sono ancora attivi quando flush_rewrite_rules() viene eseguito durante questo hook (che è normalmente il metodo consigliato per svuotare le regole di riscrittura).

La soluzione più pulita che ho trovato alla fine è stata quella di svuotare le regole di riscrittura dopo la registrazione dei post type, ma ovviamente solo se tale operazione fosse effettivamente necessaria (perché l'operazione è lenta). Nel mio caso, ho diversi post type personalizzati che ereditano da una singola classe base, quindi era desiderabile implementare il codice che esegue lo svuotamento lì.

Se lo svuotamento è necessario può essere deciso esaminando l'output di get_option( 'rewrite_rules' ):

class MyPostTypeClass {

public final function register_as_custom_post_type() {
    ...   //esegui tutta la configurazione del tuo post type qui     
    $args = array(
                  ... //popola gli altri argomenti come ritieni opportuno
                  'rewrite' => array('slug' => 'slug-del-tuo-post-type')
                 );
    register_post_type('nome-del-tuo-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);
}
}

Svantaggi:

  • Dipende in qualche misura dalle esatte regole di riscrittura che WordPress genera durante register_post_type().
  • Verificare se lo svuotamento è necessario durante ogni caricamento di pagina crea anche un certo overhead.

Vantaggi:

  • Completamente incapsulato nella classe che rappresenta il post type.
  • Svuota le regole di riscrittura solo se realmente necessario.

Usa questo metodo solo se non puoi registrare il tuo post type in una funzione statica che può essere chiamata sia durante init che l'activation_hook!

La dipendenza da come appaiono le regole di riscrittura generate durante register_post_type() può essere mitigata sostituendo il test if(strpos($key, $args['rewrite']['slug'] ) === 0) con qualcosa di più elaborato, ad esempio un'espressione regolare.

21 lug 2018 12:08:20
0

@tazo-todua anche per me ha funzionato quando uso il multisite.

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();
}
11 nov 2016 23:30:54
0

Se vuoi eseguire flush_rewrite_rules quando QUALSIASI plugin viene attivato o disattivato

add_action('init', function(){

    // Ottieni il percorso di tutti i plugin installati
    $pluginsInstalledPaths = glob(WP_PLUGIN_DIR . '/*', GLOB_ONLYDIR);

    foreach ($pluginsInstalledPaths as $pluginPath) {
        // Ottieni tutti i file PHP disponibili nella directory principale del plugin
        $files = glob($pluginPath . '/*.php');
        foreach ($files as $file) {
            $contents = file_get_contents($file);
            // Se il file contiene "Plugin Name" è il file principale del plugin
            if (preg_match('/\/\*\*[^\/]*?Plugin Name:/', $contents)) {
                add_action('activate_' . plugin_basename($file), function(){
                    flush_rewrite_rules();
                });
                add_action('deactivate_' . plugin_basename($file), function(){
                    flush_rewrite_rules();
                });
            }
        }
    }
});
26 gen 2022 15:43:39
0
-1

LA MIA SOLUZIONE TROVATA È STATA:

global $wp_rewrite; $wp_rewrite->flush_rules(); $wp_rewrite->init();
20 apr 2015 10:00:51
0
-1

Aggiungi questo codice ogni volta che vuoi svuotare le regole di riscrittura, ad esempio durante l'attivazione del tuo plugin o in qualsiasi evento desideri.

add_action('init','flush_rewrite_rules');
22 giu 2023 14:41:10