Unde, Când și Cum să Goliți Corect Regulile de Rescriere în Contextul unui Plugin?

15 nov. 2013, 19:20:41
Vizualizări: 25.7K
Voturi: 16

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.

3
Comentarii

se pare că poate ai ordinea lucrurilor greșită, este greu de spus fără să vedem niște cod. pagina de administrare a permalinkurilor apelează doar flush_rewrite_rules, care doar șterge opțiunea rewrite_rules și o regenerează, poți deschide fișierul wp-admin/options-permalinks.php și să vezi unde se întâmplă asta. deoarece această operațiune doar șterge întreaga opțiune, nu este posibil să flush-uiți parțial regulile.

Milo Milo
15 nov. 2013 20:27:18

@Milo cred că ai dreptate. Am o clasă care este încărcată pe init care înregistrează tipurile de postări. Am presupus că setările paginii erau salvate, iar pagina se reîncărca... apoi declanșa din nou hook-ul init pentru a înregistra tipurile de postări necesare. Așa că am crezut că tipurile de postări ar fi deja încărcate și tot ce trebuia să fac era să actualizez opțiunea, apoi să flush-uiesc regulile de rewrite din pagina de setări a pluginului meu. Voi posta un răspuns cu cum am găsit o soluție.

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

Doar un avertisment: flush_rewrite_rules() în pluginul meu s-a dovedit a fi parte a problemei pentru mine. Am șters hook-ul php și am ajuns doar să actualizez permalinkurile manual, iar erorile 404 pentru CPT-urile mele au dispărut.

myol myol
20 oct. 2014 11:38:33
Toate răspunsurile la întrebare 8
2

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

Vezi articolul din codex

Îmi cer scuze anticipat, nu am reușit să parcurg întrebarea ta complet, așa că acesta este un răspuns standard.

15 nov. 2013 19:37:09
Comentarii

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.

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

Mă gândeam că ar putea fi cazul, dar eram destul de obosit când citeam întrebarea ta. Soluția lui ialocin pare promițătoare, sper că ai reușit să o rezolvi.

helgatheviking helgatheviking
17 nov. 2013 02:22:41
4

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

15 nov. 2013 20:47:37
Comentarii

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

helgatheviking helgatheviking
17 nov. 2013 02:23:11

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

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

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.

MatthewLee MatthewLee
15 feb. 2014 19:59:35

Diferența este într-adevăr minoră, mai ales dacă transient-urile sunt permanente, fără termen de expirare, dar desigur, transient-urile au și alte capabilități și beneficii care sunt utile. @MatthewLee

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

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:

  1. Actualizați setările plugin-ului.
  2. Î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.
  3. 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.

15 nov. 2013 21:38:08
0

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ă.

21 iul. 2018 12:08:20
0

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

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();
                });
            }
        }
    }
});
26 ian. 2022 15:43:39
0
-1

SOLUȚIA PE CARE AM GĂSIT-O A FOST:

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

Adaugă acest cod ori de câte ori dorești să resetezi regulile de rescriere, de exemplu la activarea plugin-ului tău sau la orice eveniment dorit.

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