Ho bisogno di aiuto con add_rewrite_rule
SOLUZIONE
Ho optato per l'Aggiornamento 3 e sono riuscito a farlo funzionare. Quello che avevo frainteso era che credevo che una regola di riscrittura avrebbe cambiato designers/?designer=some-designer&bid=9
in /designers/some-designer
. Ma è ovviamente il contrario.
Ho fatto alcune ricerche, ma non capisco bene come usare add_rewrite_rule().
Questo post è abbastanza simile a ciò di cui ho bisogno, ma ho davvero bisogno di tutto quel codice?
Il mio link attuale è questo:
http://www.norwegianfashion.no/designers/?designer=Batlak-og-Selvig&bid=9
Quello che voglio è questo
http://www.norwegianfashion.no/designers/Batlak-og-Selvig/
- Come uso
add_rewrite_rule()
? - Ho bisogno di passare l'ID del designer (bid). Come posso farlo usando le regole di riscrittura senza che appaia nell'URL?
Aggiornamento 1
Ho trovato questo che è un po' più esplicativo. Ma non funziona:
// Aggiunge nuove regole di riscrittura
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)
);
// Aggiungi sempre le tue regole in cima, per assicurarti che abbiano priorità
$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')
Aggiornamento 2
Ecco un'altra soluzione che ho provato, che Jan Fabry ha suggerito in un altro thread. L'ho messa nel mio functions.php, ma non ha alcun effetto.
add_action('generate_rewrite_rules', 'add_rewrite_rules');
add_filter('query_vars', 'query_vars');
/* Regole di riscrittura personalizzate per i designer
------------------------------------------------------------------------------*/
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;
}
Aggiornamento 3
Ho trovato alcuni esempi qui anche. Ma neanche questo funziona :(
add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');
// Ricordati di usare flush_rules() quando aggiungi regole
function flushRules(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
// Aggiunta di una nuova regola
function wp_insertMyRewriteRules($rules)
{
$newrules = array();
$newrules['(designers)/(\d*)$'] = 'index.php?pagename=designers&designer=$matches[1]';
return $newrules + $rules;
}
// Aggiunta della variabile bid in modo che WP la riconosca
function wp_insertMyRewriteQueryVars($vars)
{
array_push($vars, 'designer');
return $vars;
}
Aggiornamento 4 Ho provato anche questa soluzione, ma ancora nessun successo.
add_filter('search_rewrite_rules', 'designers_createRewriteRules');
function designers_createRewriteRules($rewrite) {
global $wp_rewrite;
// aggiungi token di riscrittura
$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 );
}
Aggiornamento 5
Sembra che le mie regole di riscrittura non vengano aggiunte.
Eseguendo il seguente comando dopo aver aggiunto nuove regole: print_r($wp_rewrite)
, non include le mie nuove regole di riscrittura.
Aggiornamento 6
Ho testato la soluzione di Jan. Ma l'URL non cambia :(
/* Script di inizializzazione per il template NF
------------------------------------------------------------------------------*/
add_action('after_setup_theme','norwegianfashion_setup');
if ( ! function_exists( 'norwegianfashion_setup' ) ):
function norwegianfashion_setup() {
/* Qui faccio molte cose */
// URL SEO friendly per i designer
add_action( 'init', 'wpa5413_init' );
add_filter( 'query_vars', 'wpa5413_query_vars' );
}
endif;
/* Regole di riscrittura personalizzate per i designer
------------------------------------------------------------------------------*/
function wpa5413_init()
{
// Ricordati di eseguire flush delle regole manualmente una volta dopo aver aggiunto questo codice!
add_rewrite_rule(
'designers/([^/]+)/?',
'index.php?pagename=designers&designer=$matches[1]',
'top' );
}
function wpa5413_query_vars( $query_vars )
{
$query_vars[] = 'designer';
return $query_vars;
}
Apprezzerei davvero tanto se qualcuno potesse aiutarmi a risolvere questo problema.

Alcune informazioni sulle regole di riscrittura
Il sistema di riscrittura di WP può sembrare complicato, ma in realtà non è così difficile da capire come funziona. Viene utilizzato per interpretare gli URL leggibili (/designers/
) come se fossero non leggibili (/index.php?pagename=designers
). L'idea di base è che hai una lista di regole di riscrittura, espressioni regolari che possono corrispondere agli URL in ingresso e riscriverli in altri URL, principalmente nella forma di index.php
con alcune variabili di query. Queste variabili sono impostate sulle parti dell'espressione regolare che corrispondono all'URL. Le regole vengono valutate dall'alto verso il basso, quindi se due regole potrebbero corrispondere, vince la prima.
Queste regole di riscrittura sono memorizzate nel database chiamando flush_rewrite_rules()
, ma poiché generare e scrivere queste regole è un'operazione costosa, non dovresti farlo ad ogni init
. Invece, lo fai solo quando cambi le regole: probabilmente all'attivazione del plugin (usando register_activation_hook()
), o manualmente visitando la pagina delle impostazioni dei Permalinks (perché è difficile farlo automaticamente all'attivazione del tema). Se non svuoti le regole, chiamare add_rewrite_rule()
non ha alcun effetto. Non è un problema chiamare add_rewrite_rule()
ad ogni init
, anche dopo aver svuotato le regole.
Ci sono molti modi per aggiungere le tue regole di riscrittura, e se vuoi aggiungere solo una regola, puoi farlo con add_rewrite_rule()
. Poiché le regole per post, pagine, tassonomie, ... risultano in più regole, sono create con funzioni di alto livello come add_rewrite_tag()
, add_permastruct()
, ... Ma queste non sono necessarie per il caso semplice che abbiamo qui.
Ci sono anche alcuni filtri, quindi puoi anche aggiungere le tue regole usando gli hook generate_rewrite_rules
o generate_rewrite_rules_array
. Questi ti danno un controllo molto dettagliato su tutte le regole, ma ancora, add_rewrite_rule()
è sufficiente se vuoi solo aggiungere una regola.
Ho creato un piccolo plugin che ti permette di analizzare le regole di riscrittura correnti, e (ovviamente) ti consiglio di usarlo quando provi a cambiare qualcosa.
Ottenere le tue informazioni aggiuntive dall'URL
Costruiamo sull'esempio che hai fornito. Hai il brand di designer Batlak og Selvig
, con l'ID numerico (bid
) 9
. Non vuoi questo ID nell'URL, ma solo il nome. Chiamiamo la versione URL-friendly del nome (senza spazi o caratteri speciali) lo slug: Batlak-og-Selvig
.
In generale, l'URL dovrebbe contenere tutte le informazioni per identificare il contenuto che vuoi mostrare sulla pagina. Puoi usare i cookie o le richieste POST per memorizzare l'ID effettivo del designer che vuoi visualizzare, ma questo si interromperà se qualcuno condivide il link, inviandolo via mail, Facebook, Twitter, o semplicemente leggendolo ad alta voce al telefono. Se non vuoi usare l'ID numerico nel tuo URL, dovresti assicurarti che lo slug sia univoco: allora prima fai una ricerca dell'ID basata sullo slug, e continui come hai fatto prima.
Quindi quello che abbiamo imparato ora è che vogliamo aggiungere una regola di riscrittura per il pattern "/designers/
seguito da qualsiasi cosa fino al prossimo /
", e salvare quella "qualsiasi cosa" nella variabile di query designer_slug
. Nel tuo caso credo che tu voglia anche usare la pagina con lo slug designers
come contenuto generale della pagina, quindi lo diremo anche a WordPress.
add_action( 'init', 'wpa5413_init' );
function wpa5413_init()
{
// Ricorda di svuotare manualmente le regole una volta dopo aver aggiunto questo codice!
add_rewrite_rule(
// La regex per corrispondere all'URL in ingresso
'designers/([^/]+)/?',
// L'URL interno risultante: `index.php` perché usiamo ancora WordPress
// `pagename` perché usiamo questa pagina di WordPress
// `designer_slug` perché assegniamo la prima parte catturata dalla regex a questa variabile
'index.php?pagename=designers&designer_slug=$matches[1]',
// Questo è un URL piuttosto specifico, quindi lo aggiungiamo in cima alla lista
// Altrimenti, le regole "catch-all" in fondo (per pagine e allegati) "vinceranno"
'top' );
}
L'unica cosa rimasta da fare è dire a WordPress di mantenere anche designer_slug
nelle variabili di query, così puoi accedervi più tardi. WordPress usa una whitelist di variabili di query consentite, per impedire alle persone di modificare ogni parametro della query dei post tramite l'URL. Tutto ciò che non è in questa lista viene ignorato. Basta agganciarsi all'hook query_vars
e aggiungere la tua variabile extra:
add_filter( 'query_vars', 'wpa5413_query_vars' );
function wpa5413_query_vars( $query_vars )
{
$query_vars[] = 'designer_slug';
return $query_vars;
}
Come puoi vedere, questa risposta è sostanzialmente la stessa della mia risposta precedente, ma senza lo svuotamento delle regole nel codice (così puoi usarlo nel functions.php
del tuo tema invece che in un plugin), e con un po' più di certezza e spiegazione perché ho imparato molto sulle regole di riscrittura da (e a causa di) aver risposto alla tua prima domanda.
Discussione nella chat room
Abbiamo chiarito i problemi finali per questa domanda nella chat room. Alla fine, Steven ha usato l'hook generate_rewrite_rules
, perché la funzione add_rewrite_rule()
non sembrava funzionare per lui.

Grazie per il feedback esaustivo! Continuo a vedere index.php?pagename=designers
. La mia pagina/template Designers
utilizza il file designers.php. Non dovremmo usare questo?

@Steven: pagename
è lo slug della pagina WordPress che vuoi visualizzare (record nel database). Questa pagina può poi indicare che vuole utilizzare il file template designers.php
nell'area di amministrazione di WP. Quindi punti allo slug della pagina, non al nome del template, poiché lo stesso template può essere utilizzato per più pagine: in questo caso WordPress non sa cosa vuoi fare.

Vedi il mio Aggiornamento 6, questo è il codice che sto testando ora. Ma l'URL rimane ancora con /?designer=Batlak-og-Selvig&bid=9
:( C'è un modo per verificare se le regole di riscrittura sono state aggiunte?

@Steven: Penso che tu stia complicando troppo il modo in cui configuri gli hook. Rimuovi la funzione add_rewrite_rules()
e chiama add_filter()/add_action()
direttamente. Se questo è in un file del tema, rimuovi flush_rewrite_rules()
e visita semplicemente la pagina delle impostazioni dei permalink per svuotare le regole (o aggiungile in wpse5413_init()
e rimuovile dopo). E il mio plugin mostra le regole di riscrittura correnti. Ricorda che questo cambia solo il modo in cui gli URL in entrata vengono gestiti, non come il tuo codice scriverà gli URL nell'HTML.

@Jan Fabry: Ok, ho aggiornato il codice per riflettere le modifiche, rimuovendo la funzione add_rewrite_rules()
. Ho anche provato a posizionare add_filter
e add_Action
all'inizio del mio file di funzioni. L'unico modo che vedo per svuotare manualmente i permalink è premere il pulsante salva? Tuttavia, l'URL nel browser rimane lo stesso :(

@Steven: Non penso che tu debba nemmeno premere il pulsante salva, basta aprire la pagina dei permalink per svuotarli. E ancora, questo aggiungerà solo la capacità per WordPress di accettare URL /designers/designer-slug/
, devi cambiare tu stesso i punti in cui scrivi questi URL nel tuo HTML. Provalo andando su /designers/Batlak-og-Selvig/
tu stesso, se funziona, trova tutti i posti che generano questi URL e cambiali per utilizzare la nuova struttura.

Ah, ora credo di iniziare a capire. Pensavo che le regole di riscrittura avrebbero cambiato come l'URL veniva visualizzato nella barra degli indirizzi del browser. Ma quello che significa è che devo effettivamente generare l'URL www.mysite.com/batlat-og-selvig/9
e poi questo viene "tradotto" in /?designer=Batlak-og-Selvig&bid=9

@Steven: Sì, esatto: le regole di riscrittura gestiscono i link in entrata e (solo in alcuni casi selezionati) non influenzano i link generati nel tuo codice.

@Jan Fabry: Ok, ora ho creato uno slug unico per ogni designer. Il link alla pagina del designer ora appare così http://norwegianfashion.com/designers/batlak-og-selvig
(sto usando .com su localhost). Ma la mia regola di riscrittura non lo intercetta. Ottengo semplicemente un errore 404 Pagina non trovata.

@Steven: E la tua regola di riscrittura è in lista, in cima? Se puoi venire nella chat room, possiamo provare a risolverlo lì.

@Jan Fabry: Dovrei essere in grado di usare $_GET['designer'] per recuperare lo slug/nome del designer?

@Steven: Penso che il metodo "ufficiale" sia $wp_query->get( 'designer' )

@Jan Fabry: Grazie Jan. Ora puoi vederlo in azione :) http://www.norwegianfashion.no/designers/batlak-og-selvig/

jan - quale sarebbe pagename se volessimo caricare un post di un custom post_type (directors), chiamato test-director in single-directors.php. Attualmente sto avendo problemi a farlo funzionare; 'directors/(.+?)/showreels/([^/])/video/([^/])/?', 'index.php?whatgoeshere!!!=???&showreel=$matches[2]&video=$matches[3]'
