Am nevoie de ajutor cu add_rewrite_rule
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/
- Cum folosesc
add_rewrite_rule()
? - 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ă.

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.

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

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

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: 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: 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: Ș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: Ar trebui să pot folosi $_GET['designer'] pentru a obține slug-ul/numele designerului?

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

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

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]'
