Unde, Când și Cum să Goliți Corect Regulile de Rescriere în Contextul unui Plugin?
Am o problemă destul de ciudată cu regulile de rescriere care nu se golesc corespunzător.
Am încercat să folosesc flush_rewrite_rules();
și flush_rewrite_rules(true);
.
De asemenea, am încercat să globalizez $wp_rewrite
folosind $wp_rewrite->flush_rules();
și $wp_rewrite->flush_rules(true);
Niciuna dintre aceste metode nu pare să golească corect regulile de rescriere. Aceste apeluri într-adevăr golesc regulile de rescriere când sunt apelate. De unde știu asta? Folosind soluția pentru depanarea golirii regulilor de rescriere.
În prezent, am regulile de rescriere golite la activarea și dezactivarea plugin-ului. Nu sunt probleme aici.
Am o pagină de setări administrative pentru plugin unde utilizatorii pot configura plugin-ul. Unele dintre setări ajustează structura permalink-urilor, astfel încât regulile de rescriere trebuie să fie golite la "Salvare Setări" în pagina de administrare. (Folosește standardul update_option();
pentru salvarea setărilor.)
Aș dori să menționez că în funcție de setările specificate, tipurile de postări personalizate sunt create pentru a se potrivi setărilor specificate de utilizator. Astfel, regulile de rescriere trebuie să fie golite imediat după ce setările sunt salvate. Aici lucrurile nu funcționează corespunzător.
Soluția de depanare a regulilor de rescriere de mai sus oferită de @toscho
arată că se golesc o mulțime de reguli de rescriere. Cu toate acestea, când vizitez elementul singular al tipului de postare personalizat sau chiar arhiva tipului de postare personalizat, fiecare returnează erori 404.
Tipul de postare personalizat este înregistrat corect și corespunzător. Știu cu siguranță că aceasta nu este problema.
Imediat după salvarea setărilor paginii de administrare a plugin-ului. Tipurile de postări personalizate sunt create, structura permalink-urilor este ajustată și toate regulile de rescriere sunt încercate să fie golite.
Tipurile de postări personalizate sunt apoi încărcate întotdeauna și încărcate pe init
ca de obicei.
Din anumite motive, regulile de rescriere nu se golesc corespunzător, deoarece, așa cum am spus înainte, vizitarea secțiunilor singulare sau de arhivă ale tipului de postare personalizat returnează erori 404.
Acum partea ciudată, dacă tot ce fac este să vizitez pagina de setări a permalink-urilor din administrare și apoi să mă întorc la frontend pentru a vizualiza secțiunile singulare sau de arhivă ale tipului de postare personalizat, acestea funcționează magic așa cum era de așteptat.
Ce face acea pagină de setări a permalink-urilor din administrare pe care eu nu o fac, care permite golirea corespunzătoare a regulilor de rescriere și ale mele nu?
Vreau să spun, ca o soluție temporară, redirecționez utilizatorul către pagina de setări a permalink-urilor după salvarea paginii de setări administrative a plugin-ului, dar aceasta nu este o soluție ideală. Aș prefera ca regulile de rescriere să se golească corect în codul plugin-ului meu.
Există un anumit punct în WordPress unde golirea regulilor de rescriere nu mai golește TOATE regulile?
admin_menu
- Pagina de setări a plugin-ului este adăugată la administrarea WordPress.
add_options_page()
- Pagina de setări a plugin-ului este adăugată sub meniul Setări.
Pagina de setări este redată în callback-ul pentru add_options_page()
. Aici este, de asemenea, unde $_POST
este procesat pentru actualizarea setărilor plugin-ului și golirea regulilor de rescriere.
Deoarece aceasta este deja o întrebare lungă, aș fi dispus să furnizez blocuri de cod (dacă ajută) într-un link extern pentru a ajuta la producerea unui răspuns valid.

Cel mai bun loc pentru a reseta regulile de rescriere este la activarea/dezactivarea plugin-ului.
function myplugin_activate() {
// înregistrează taxonomii/tipuri de postări aici
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'myplugin_activate' );
function myplugin_deactivate() {
flush_rewrite_rules();
}
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );
Îmi cer scuze anticipat, nu am reușit să parcurg întrebarea ta complet, așa că acesta este un răspuns standard.

Mulțumesc pentru sugestie, dar sunt conștient de asta. Problema nu este legată de activarea/dezactivarea pluginului. Are de-a face cu utilizatorii care modifică setările pluginului deja activ, ceea ce ajustează regulile de rescriere, necesitând astfel un flush.

Este greu de spus ce nu funcționează fără a vedea codul tău. Dar după salvarea unor setări, este practic să folosești hook-ul admin_init
așa cum este arătat mai jos pentru a reîncărca regulile de rescriere.
Cod:
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);
}
}
Trebuie să setezi opțiunea undeva pe pagina de setări sau mai exact undeva în procesul de salvare a setărilor. A face acest lucru fără opțiune este prost, pentru că nu vrei să reîncarci regulile de fiecare dată.
Notă: netestat

Sau poți folosi un transient poate? Dar cu siguranță +1 pentru a nu reseta regulile la fiecare admin_init.

Ai dreptate, desigur, legat de transient, cred că am optat pentru *_option()
din cauza paginii de setări. @helgatheviking

Aceasta a fost foarte util. Am avut o situație similară cu Michael. Am ajuns să încorporez sugestia lui helga de a folosi un transient și l-am setat în funcția de validare pentru setări. Am ajuns să fie nevoie să setez transient la false după resetare, altfel continua să reseteze la fiecare încărcare a paginii de administrare până când transient expira. Deci, din punct de vedere funcțional, folosirea unei opțiuni sau a unui transient a fost același lucru. Cred că transient ar putea fi mai bun doar pentru a păstra tabelul de opțiuni mai curat. Dar e un detaliu minor.

Aveam un fișier de clasă pentru tipurile de postări care era responsabil cu citirea setărilor opțiunilor plugin-ului și crearea tipurilor de postări personalizate necesare pe baza setărilor specificate de utilizator.
Acest fișier de clasă pentru tipurile de postări era încărcat pe hook-ul init
.
Am crezut că tot ce trebuie să fac este să actualizez setările plugin-ului, apoi să resetez regulile de rescriere. Deoarece clasa pentru tipurile de postări era deja încărcată pe baza setărilor plugin-ului. Dar cu paginile de administrare, acestea sunt încărcate DUPĂ hook-ul init
.
Tipurile de postări nu au fost niciodată înregistrate, deoarece setările nu erau de fapt setate încă. Clasa de înregistrare a tipurilor de postări a fost întreruptă prematur fără ca vreun tip de postare să fie înregistrat.
Soluția a fost:
- Actualizați setările plugin-ului.
- Încărcați fișierul clasei pentru tipurile de postări DOAR o dată aici, astfel încât noile reguli de rescriere să fie create.
- Resetați regulile de rescriere.
(Anterior... pasul 2 lipsea -- După cum am menționat mai sus...)
De acum încolo, tipurile de postări vor fi încărcate pe hook-ul init
și vor avea setările deja specificate, permițând crearea tipurilor de postări și asocierea lor cu regulile de rescriere adecvate.
Din nu știu ce motiv, a trebuit să adaug un apel JavaScript pentru a redirecționa către pagina curentă, după efectuarea celor trei pași de mai sus.
De asemenea, a trebuit să adaug un apel la flush_rewrite_rules();
pe pagina de setări de administrare a plugin-ului.
Deci, pentru a mă asigura că totul este resetat...
Pasul 1) Navigați la pagina de setări de administrare a plugin-ului. -- Resetare inițială.
Pasul 2) Actualizați setările plugin-ului. -- A doua resetare.
Pasul 3) Pagina se redirecționează către pagina de setări a plugin-ului. Cauzând... A treia și ultima resetare (la fel ca resetarea inițială -- Se face automat când se vizitează pagina de setări a plugin-ului)
Nu spun că aceasta este o soluție practică, dar a funcționat pentru mine. O problemă foarte ciudată și cel mai probabil are legătură cu infrastructura mea de codare.

Aveam exact aceeași problemă. În plugin-ul meu, am tipuri de postări care sunt create dinamic. Prin urmare, ele nu pot fi înregistrate prin register_post_type()
într-o metodă statică în timpul activation_hook
și, astfel, nu sunt încă active când flush_rewrite_rules()
este executat în acest hook (care este în mod normal metoda recomandată de a reîmprospăta regulile de rescriere).
Cea mai curată soluție la care am putut ajunge în final a fost să reîmprospăt regulile de rescriere după înregistrarea tipurilor de postări, dar, desigur, doar dacă o astfel de reîmprospătare era cu adevărat necesară (deoarece operația este lentă). În cazul meu, am de fapt mai multe tipuri de postări personalizate care moștenesc dintr-o singură clasă de bază, așa că a fost de dorit să implementez codul care face reîmprospătarea acolo.
Dacă reîmprospătarea este necesară poate fi decisă prin examinarea rezultatului get_option( 'rewrite_rules' )
:
class MyPostTypeClass {
public final function register_as_custom_post_type() {
... //fă toată configurarea tipului tău de postare aici
$args = array(
... //completează celelalte argumente după cum consideri potrivit
'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);
}
}
Dezavantaje:
- Se bazează într-o oarecare măsură pe exact ce reguli de rescriere generează WP în timpul
register_post_type()
. - Verificarea dacă reîmprospătarea este necesară în timpul fiecărei încărcări de pagină creează și ea o anumită suprasarcină.
Avantaje:
- Complet încapsulat în clasa care reprezintă tipul de postare.
- Reîmprospătează regulile de rescriere doar dacă este cu adevărat necesar.
Folosește această soluție doar dacă nu poți înregistra tipul tău de postare într-o funcție statică care poate fi apelată atât în init
cât și în activation_hook
!
Dependența de modul în care arată regulile de rescriere generate în timpul register_post_type()
poate fi atenuată prin înlocuirea testului if(strpos($key, $args['rewrite']['slug'] ) === 0)
cu ceva mai elaborat, de exemplu, o expresie regulată.

@tazo-todua asta a funcționat și pentru mine când am folosit 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();
}

Dacă dorești să apelezi flush_rewrite_rules atunci când ORICE plugin este activat sau dezactivat
add_action('init', function(){
// Obține calea fiecărui plugin instalat
$pluginsInstalledPaths = glob(WP_PLUGIN_DIR . '/*', GLOB_ONLYDIR);
foreach ($pluginsInstalledPaths as $pluginPath) {
// Obține toate fișierele PHP disponibile în directorul rădăcină al pluginului
$files = glob($pluginPath . '/*.php');
foreach ($files as $file) {
$contents = file_get_contents($file);
// Dacă fișierul conține "Plugin Name" înseamnă că este fișierul principal al pluginului
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();
});
}
}
}
});
