Am nevoie de ajutor cu add_rewrite_rule

15 dec. 2010, 17:04:34
Vizualizări: 69.2K
Voturi: 58

SOLUȚIE


Am mers cu Actualizarea 3 și am reușit să o fac să funcționeze. Ceea ce am înțeles greșit a fost că am crezut că o regulă de rescriere ar schimba designers/?designer=some-designer&bid=9 în /designers/some-designer. Dar este, bineînțeles, invers.


Am făcut câteva cercetări, dar nu înțeleg exact cum să folosesc add_rewrite_rule().

Această postare este destul de aproape de ceea ce am nevoie, dar chiar am nevoie de atât de mult cod?

Link-ul meu actual este acesta:
http://www.norwegianfashion.no/designers/?designer=Batlak-og-Selvig&bid=9
Ceea ce vreau este acesta
http://www.norwegianfashion.no/designers/Batlak-og-Selvig/

  1. Cum folosesc add_rewrite_rule()?
  2. Trebuie să transmit ID-ul designerului (bid). Cum pot face asta când folosesc reguli de rescriere fără să apară în URL?

Actualizare 1

Am găsit asta care este puțin mai explicativă. Dar nu funcționează:

function add_rewrite_rules( $wp_rewrite ) 
{
    $new_rules = array(
        '('.$template_page_name.')/designers/(.*?)/?([0-9]{1,})/?$' => 'designers.php?designer='.
        $wp_rewrite->preg_index(1).'&bid='.
        $wp_rewrite->preg_index(2)
    );
       // Adaugă întotdeauna regulile tale în partea de sus, pentru a te asigura că regulile tale au prioritate
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');

function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}
add_filter('query_vars', 'query_vars')

Actualizare 2

Aici este o altă soluție pe care am încercat-o, pe care Jan Fabry a sugerat-o într-un alt thread. Am pus-o în functions.php, dar nu are niciun efect.

add_action('generate_rewrite_rules', 'add_rewrite_rules');
add_filter('query_vars', 'query_vars');

/* Reguli personalizate de rescriere pentru designeri
------------------------------------------------------------------------------*/
function add_rewrite_rules( $wp_rewrite ) 
{
    add_rewrite_rule('^designers/([^/]*)/([^/]*)$ /designers/?designer=$1&bid=$2 [L]', 'top');
    flush_rewrite_rules(false);
}


function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}

Actualizare 3
Am găsit câteva exemple aici de asemenea. Dar nici acestea nu funcționează :(

add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');  

// Nu uita să folosești flush_rules() când adaugi reguli
function flushRules(){
    global $wp_rewrite;
    $wp_rewrite->flush_rules();
}

// Adăugarea unei noi reguli
function wp_insertMyRewriteRules($rules)
{
    $newrules = array();
    $newrules['(designers)/(\d*)$'] = 'index.php?pagename=designers&designer=$matches[1]';
    return $newrules + $rules;
}

// Adăugarea variabilei bid pentru ca WP să o recunoască
function wp_insertMyRewriteQueryVars($vars)
{
    array_push($vars, 'designer');
    return $vars;
}

Actualizare 4 Am încercat și această soluție, dar tot fără succes.

add_filter('search_rewrite_rules', 'designers_createRewriteRules');

function designers_createRewriteRules($rewrite) {
global $wp_rewrite;

// adăugare tokeni pentru rescriere
$designer_token = '%designers%';
$wp_rewrite->add_rewrite_tag($designer_token, '(.+)', 'designers=');

$bid_token = '%bid%';
$wp_rewrite->add_rewrite_tag($bid_token, '(.+)', 'bid=');

$keywords_structure = $wp_rewrite->root . "designers/$designer_token/$bid_token";
$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);

return ( $rewrite + $keywords_rewrite );

}

Actualizare 5
Se pare că regulile mele de rescriere nu sunt adăugate. Executarea următorului cod după adăugarea noilor reguli: print_r($wp_rewrite), nu include noile mele reguli de rescriere.

Actualizare 6
Am testat soluția lui Jan. Dar URL-ul nu se schimbă :(

/* Script de inițializare pentru șablonul NF
------------------------------------------------------------------------------*/   
add_action('after_setup_theme','norwegianfashion_setup');

if ( ! function_exists( 'norwegianfashion_setup' ) ):

  function norwegianfashion_setup() { 
    /* Aici fac multe lucruri */

    // URL SEO friendly pentru designeri
    add_action( 'init', 'wpa5413_init' );
    add_filter( 'query_vars', 'wpa5413_query_vars' );
  }

endif;


/* Reguli personalizate de rescriere pentru designeri
------------------------------------------------------------------------------*/
function wpa5413_init()
{
    // Nu uita să reîmprospătezi regulile manual o dată după ce ai adăugat acest cod!
    add_rewrite_rule(
        'designers/([^/]+)/?',
        'index.php?pagename=designers&designer=$matches[1]',
        'top' );
}

function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer';
    return $query_vars;
}

Aș aprecia foarte mult dacă cineva ar putea să mă ajute să rezolv această problemă.

4
Comentarii

Aceasta arată foarte similar cu prima întrebare pe care ai adresat-o aici și pentru care am dat un răspuns. Situația s-a schimbat de atunci, astfel încât răspunsul meu nu mai este valid? Dacă nu dorești ca ID-ul designerului să apară în URL-ul tău, va trebui să convertești "slug-ul" în ID singur, WordPress nu poate face asta pentru tine. Designerii sunt încă obiecte externe?

Jan Fabry Jan Fabry
16 dec. 2010 00:47:11

@Jan Fabry Da, am descoperit asta după ce am postat (am uitat). Acum înțeleg mai bine și sugestia ta. Vezi codul meu actualizat aici. Designerii mei sunt încă intrări într-o bază de date personalizată. Este posibil să folosesc POST în loc de GET pentru a trimite bid?

Steven Steven
16 dec. 2010 01:04:44

Folosirea unei cereri POST nu va funcționa dacă copiez link-ul și îl trimit cuiva altcuiva. Este o problemă să faci slug-ul unic și să faci căutarea datelor de acolo?

Jan Fabry Jan Fabry
16 dec. 2010 01:57:32

@Jan Fabry: Ce înțelegi prin slug? Obținerea datelor Designerului este mult mai ușoară folosindbiddecâtdesigner`

Steven Steven
16 dec. 2010 03:18:13
Toate răspunsurile la întrebare 1
15
91

Câteva informații de bază despre regulile de rescriere

Sistemul WP Rewrite pare complicat, dar de fapt nu este atât de greu de înțeles cum funcționează. Este folosit pentru a analiza URL-uri prietenoase (/designeri/) ca și cum ar fi ne-prietenoase (/index.php?pagename=designeri). Ideea de bază este că ai o listă de reguli de rescriere, expresii regulate care pot potrivi URL-urile primite și le pot rescrie în alte URL-uri, în mare parte sub forma index.php cu unele variabile de interogare. Aceste variabile sunt setate la părțile expresiei regulate care au potrivit URL-ul. Regulile sunt evaluate de sus în jos, așa că dacă două reguli ar putea potrivi, prima "câștigă".

Aceste reguli de rescriere sunt stocate în baza de date prin apelarea flush_rewrite_rules(), dar deoarece generarea și scrierea acestor reguli este o operațiune costisitoare, nu ar trebui să o faci la fiecare init. În schimb, o faci doar când schimbi regulile: probabil la activarea plugin-ului (folosind register_activation_hook()), sau manual vizitând pagina de setări Legături permanente (deoarece este greu de făcut acest lucru automat la activarea temei). Dacă nu reîmprospătezi regulile, apelarea add_rewrite_rule() nu are niciun efect. Nu este o problemă să apelezi add_rewrite_rule() la fiecare init, chiar și după ce ai reîmprospătat regulile.

Există multe modalități de a adăuga regulile tale de rescriere, iar dacă vrei să adaugi doar o regulă, poți face acest lucru cu add_rewrite_rule(). Deoarece regulile pentru articole, pagini, taxonomii, ... rezultă în multiple reguli, acestea sunt create cu funcții de nivel înalt precum add_rewrite_tag(), add_permastruct(), ... Dar acestea nu sunt necesare pentru cazul simplu pe care îl avem aici.

Există și unele filtre, așa că poți adăuga și regulile tale folosind hook-urile generate_rewrite_rules sau generate_rewrite_rules_array. Acestea îți oferă un control foarte detaliat asupra regulilor complete, dar din nou, add_rewrite_rule() este suficient dacă vrei doar să adaugi o regulă.

Am creat un mic plugin care îți permite să analizezi regulile curente de rescriere și (desigur) îți recomand să îl folosești când încerci să schimbi ceva.

Obținerea informațiilor suplimentare din URL

Să construim pe exemplul pe care l-ai dat. Ai marca de designeri Batlak og Selvig, cu ID-ul numeric (bid) 9. Nu vrei acest ID în URL, ci doar numele. Numim versiunea URL-prietenoasă a numelui (fără spații sau caractere speciale) slug-ul: Batlak-og-Selvig.

În general, URL-ul ar trebui să conțină toate informațiile pentru a identifica conținutul pe care vrei să îl afișezi pe pagină. Poți folosi cookie-uri sau cereri POST pentru a stoca ID-ul real al designerului pe care vrei să îl afișezi, dar acest lucru se va defecta dacă cineva împărtășește legătura, prin trimiterea ei prin e-mail, Facebook, Twitter, sau doar citind-o cu voce tare la telefon. Dacă nu vrei să folosești ID-ul numeric în URL-ul tău, ar trebui să te asiguri că slug-ul este unic: apoi faci mai întâi o căutare a ID-ului pe baza slug-ului și continui așa cum ai făcut înainte.

Deci, ceea ce am învățat acum este că vrem să adăugăm o regulă de rescriere pentru modelul "/designeri/ urmat de orice până la următorul /" și să salvăm acel "orice" în variabila de interogare designer_slug. În cazul tău, cred că vrei să folosești și pagina cu slug-ul designeri ca conținut general al paginii, așa că îi vom spune asta și WordPress.

add_action( 'init', 'wpa5413_init' );
function wpa5413_init()
{
    // Nu uita să reîmprospătezi regulile manual o dată după ce ai adăugat acest cod!
    add_rewrite_rule(
        // Regex-ul pentru a potrivi URL-ul primit
        'designeri/([^/]+)/?',
        // URL-ul intern rezultat: `index.php` pentru că încă folosim WordPress
        // `pagename` pentru că folosim această pagină WordPress
        // `designer_slug` pentru că atribuim prima parte capturată din regex acestei variabile
        'index.php?pagename=designeri&designer_slug=$matches[1]',
        // Acesta este un URL destul de specific, așa că îl adăugăm în partea de sus a listei
        // Altfel, regulile "prindere-toate" din partea de jos (pentru pagini și atașamente) vor "câștiga"
        'top' );
}

Singurul lucru rămas de făcut este să îi spunem WordPress să păstreze și designer_slug în variabilele de interogare, astfel încât să poți accesa mai târziu. WordPress folosește o listă albă de variabile de interogare permise, pentru a preveni oamenii să modifice fiecare parametru al interogării articolelor prin URL. Tot ce nu este pe această listă este ignorat. Doar conectează-te la hook-ul query_vars și adaugă variabila ta suplimentară:

add_filter( 'query_vars', 'wpa5413_query_vars' );
function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer_slug';
    return $query_vars;
}

După cum poți vedea, acest răspuns este practic la fel ca răspunsul meu anterior, dar fără reîmprospătarea regulilor în cod (astfel încât să poți folosi în functions.php al temei tale în loc de un plugin), și cu puțin mai multă certitudine și explicație pentru că am învățat multe despre regulile de rescriere de la (și din cauza) răspunsului la prima întrebare.

Discuție în sala de chat

Am rezolvat problemele finale pentru această întrebare în sala de chat. În final, Steven a folosit hook-ul generate_rewrite_rules, deoarece funcția add_rewrite_rule() nu părea să funcționeze pentru el.

16 dec. 2010 12:07:23
Comentarii

Mulțumesc pentru feedback-ul detaliat! Continuu să văd index.php?pagename=designers. Pagina mea / template-ul Designers utilizează fișierul designers.php. Nu ar trebui să folosim acesta?

Steven Steven
16 dec. 2010 12:18:27

@Steven: pagename reprezintă slug-ul paginii WordPress pe care dorești să o afișezi (înregistrarea din baza de date). Această pagină poate apoi să indice că dorește să utilizeze fișierul template designers.php în zona de administrare WP. Deci tu te referi la slug-ul paginii, nu la numele template-ului, deoarece același template poate fi folosit pentru multiple pagini: în acest caz WordPress nu știe ce anume dorești să faci.

Jan Fabry Jan Fabry
16 dec. 2010 12:35:00

Vezi Update 6-ul meu, acesta este codul pe care îl testez acum. Dar URL-ul rămâne tot cu /?designer=Batlak-og-Selvig&bid=9 :( Există vreo modalitate de a verifica dacă regulile de rescriere au fost adăugate?

Steven Steven
16 dec. 2010 12:43:09

@Steven: Cred că complici în mod excesiv modul în care configurezi hook-urile. Elimină funcția add_rewrite_rules() și apelează direct add_filter()/add_action(). Dacă acest cod se află într-un fișier de temă, elimină flush_rewrite_rules() și pur și simplu vizitează pagina de setări a permalink-urilor pentru a reîmprospăta regulile (sau adaugă-le în wpse5413_init() și elimină-le mai târziu). Plugin-ul meu afișează regulile curente de rescriere. Ține minte că acest lucru schimbă doar modul în care sunt gestionate URL-urile primite, nu modul în care codul tău va scrie URL-urile în HTML.

Jan Fabry Jan Fabry
16 dec. 2010 12:52:04

@Jan Fabry: Ok, am actualizat codul pentru a reflecta modificările, eliminând funcția add_rewrite_rules(). Am încercat și plasarea add_filter și add_Action chiar la începutul fișierului meu de funcții. Singura modalitate pe care o văd pentru a reîmprospăta manual permalink-urile este prin apăsarea butonului de salvare? Totuși, URL-ul din browser rămâne același :(

Steven Steven
16 dec. 2010 13:01:11

@Steven: Nu cred că trebuie măcar să apeși butonul de salvare, doar deschiderea paginii de permalink-uri va face și ea flush. Și repet, acest lucru va adăuga doar capacitatea WordPress de a accepta URL-uri de tip /designers/designer-slug/, trebuie să modifici manual locurile unde scrii aceste URL-uri în HTML-ul tău. Testează accesând manual /designers/Batlak-og-Selvig/, dacă funcționează, caută toate locurile care generează aceste URL-uri și modifică-le să folosească noua structură.

Jan Fabry Jan Fabry
16 dec. 2010 13:05:19

Ah, acum cred că încep să înțeleg. Credeam că regulile de rescriere ar schimba modul în care URL-ul este afișat în bara de adrese a browserului. Dar, de fapt, înseamnă că trebuie să afișez URL-ul www.mysite.com/batlat-og-selvig/9 și apoi acesta este "tradus" în /?designer=Batlak-og-Selvig&bid=9

Steven Steven
16 dec. 2010 13:23:54

@Steven: Da, exact: regulile de rescriere se ocupă de linkurile primite și (doar în câteva cazuri selecte) nu afectează linkurile generate în codul tău.

Jan Fabry Jan Fabry
16 dec. 2010 13:32:10

@Jan Fabry: Ok, acum am creat un slug unic pentru fiecare designer. Linkul către pagina designerului arată acum astfel http://norwegianfashion.com/designers/batlak-og-selvig (folosesc .com pe localhost). Dar regula mea de rescriere nu îl prinde. Primește doar o eroare 404 Pagină negăsită.

Steven Steven
16 dec. 2010 15:18:33

@Steven: Și regula ta de rescriere este în listă, în partea de sus? Dacă poți veni în camera de chat, putem încerca să rezolvăm acolo.

Jan Fabry Jan Fabry
16 dec. 2010 15:28:29

@Jan Fabry: Ar trebui să pot folosi $_GET['designer'] pentru a obține slug-ul/numele designerului?

Steven Steven
16 dec. 2010 20:01:46

@Steven: Cred că metoda "oficială" este $wp_query->get( 'designer' )

Jan Fabry Jan Fabry
17 dec. 2010 00:50:00

@Jan Fabry: Mulțumesc, Jan. Acum poți vedea cum funcționează :) http://www.norwegianfashion.no/designers/batlak-og-selvig/

Steven Steven
17 dec. 2010 02:09:40

jan - care ar fi pagename dacă am vrea să încărcăm un custom post_type (directors) post, numit test-director în single-directors.php. Momentan am probleme să fac asta să funcționeze; 'directors/(.+?)/showreels/([^/])/video/([^/])/?', 'index.php?whatgoeshere!!!=???&showreel=$matches[2]&video=$matches[3]'

v3nt v3nt
22 mai 2012 16:40:32

Mulțumesc mult. Din nu știu ce motiv, a trebuit să folosesc și filtrul. Conversația voastră m-a ajutat foarte mult!

Alexandre Bourlier Alexandre Bourlier
21 feb. 2015 20:20:16
Arată celelalte 10 comentarii