Percorso personalizzato per plugin in WordPress
Ok, la mia domanda è abbastanza semplice. Ho bisogno di implementare alcune regole di routing personalizzate per il mio plugin. Queste route richiederebbero un solo argomento (quindi niente di complicato) e apparirebbero così: http://www.example.org/myroute/myargument
E idealmente, questo dovrebbe richiamare una classe personalizzata e visualizzare un template personalizzato (che potrebbe accedere direttamente alla classe).
Qual è il miglior approccio per fare questo? Grazie
Devi fare tre cose importanti:
- Creare una regola di riscrittura personalizzata per trasformare parti dell'URI in valori passati a
index.php
. - Aggiungere
myroute
emyargument
alla whitelist delle variabili di query di WordPress, in modo che WordPress non le ignori quando compaiono in una stringa di query. - Svuotare le regole di riscrittura (flush rewrite rules).
Innanzitutto, ti consiglio di usare un prefisso o suffisso speciale per indicare quando l'URI deve essere considerato una di queste "route" speciali, anziché usare semplicemente http://www.example.org/myroute/myargument
. Per questo esempio, ho scelto il prefisso api
, quindi sarà http://www.example.org/api/myroute/myargument
. Ho scelto api
perché quando ho implementato qualcosa di RESTful, come sembra tu stia facendo, era per un'API.
Il Codice
add_filter( 'rewrite_rules_array', 'my_insert_rewrite_rules' );
add_filter( 'query_vars', 'my_insert_query_vars' );
add_action( 'wp_loaded', 'my_flush_rules' );
// flush_rules() se le nostre regole non sono ancora incluse
function my_flush_rules() {
$rules = get_option( 'rewrite_rules' );
if ( ! isset( $rules['api/(.*?)/(.+?)'] ) ) {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
}
// Aggiunta di una nuova regola
function my_insert_rewrite_rules( $rules ) {
$newrules = array();
$newrules['api/(.*?)/(.+?)'] = 'index.php?myroute=$matches[1]&myargument=$matches[2]';
return $newrules + $rules;
}
// Aggiunta della variabile id in modo che WP la riconosca
function my_insert_query_vars( $vars ) {
array_push( $vars, 'myroute', 'myargument' );
return $vars;
}
Spiegazione rapida
È tutto abbastanza semplice. Il pattern regex viene aggiunto a un elenco di tutte le regole di riscrittura in WordPress, e il tuo pattern personalizzato si trova in cima alla lista. Quando il pattern corrisponde, WordPress smetterà di scorrere l'elenco delle regole di riscrittura e utilizzerà i valori catturati dalla regex al posto dei riferimenti ($matches[1]
e $matches[2]
) nella stringa di query passata a index.php
.
Aggiungere le variabili di query myroute
e myargument
alla whitelist fa sì che WordPress le consideri anziché scartarle.
Modo alternativo per "namespacing" della tua route personalizzata
Se vuoi evitare di usare /api/
come prefisso, puoi usare invece una variabile/campo nella query string. Per fare ciò, dovresti cambiare la regex in qualcosa come (.*?)/(.+?)\\?api=1
e poi aggiungere api
come parametro aggiuntivo nella chiamata array_push()
fatta in my_insert_query_vars()
.
Questo modificherebbe la route personalizzata in modo che venga attivata ogni volta che api=1
è il primo elemento della query string, ad esempio verrebbe attivata per http://example.com/anytext/anytext?api=1
.
Ignora l'uso del termine "namespacing" – l'ho usato solo per brevità.
Se non usi un prefisso o un suffisso per identificare la tua route, finirai con pattern di URI in conflitto. Questo perché WordPress non avrà modo di distinguere il tuo pattern personalizzato da uno destinato a un post o una pagina. Come farebbe WordPress a sapere che myroute
non è una tassonomia, un termine o una pagina genitore?
Spero che questo ti sia utile.

Nota utile: le regole definite in my_insert_rewrite_rules
seguono l'ordine di definizione! Inizia con la regola più lunga prima e poi scendi alla più semplice, altrimenti /api/myroute sovrascriverà /api/myroute/myargument.

@npc Questo è un punto importante da tenere a mente quando si creano regole di riscrittura personalizzate, possono anche scontrarsi in questo modo. Nell'esempio sopra però, non è un problema perché /api/myroute semplicemente non sarebbe un percorso valido.

Come potrebbe qualcuno caricare un template personalizzato dalla directory del proprio plugin ogni volta che veniva richiesta la pagina http://www.example.org/api/myroute/myargument?

Ecco la soluzione reale e completa fornita da WordPress: https://codex.wordpress.org/Rewrite_API/add_rewrite_rule

Per ampliare un po' quello che ha fatto eddiemoya sopra:
Come l'autore originale di questa domanda, volevo creare un rewrite personalizzato e fornire anche un template personalizzato per quella pagina. Il codice di edditmoya mi ha indirizzato nella giusta direzione e ho aggiunto una funzione extra per servire il mio template personalizzato quando la pagina viene visitata.
Il template personalizzato potrebbe trovarsi ovunque, nel mio caso è memorizzato nella directory del plugin.
Volevo anche verificare se le regole di rewrite dovevano essere aggiornate solo durante l'attivazione del plugin, quindi ho inserito questa logica in un register_activation_hook
Vedi sotto per l'esempio completo di quello che ho fatto:
AGGIORNATO semplificato in base ai consigli di milo
class Your_Class
{
public function init()
{
add_filter( 'template_include', array( $this, 'include_template' ) );
add_filter( 'init', array( $this, 'rewrite_rules' ) );
}
public function include_template( $template )
{
//prova a ottenere la query var che abbiamo registrato nella nostra funzione query_vars()
$account_page = get_query_var( 'account_page' );
//se la query var contiene dati, dobbiamo essere sulla pagina giusta, carica il nostro template personalizzato
if ( $account_page ) {
return PATH_TO_PLUGIN_TEMPLATES_DIR . 'register.php';
}
return $template;
}
public function flush_rules()
{
$this->rewrite_rules();
flush_rewrite_rules();
}
public function rewrite_rules()
{
add_rewrite_rule( 'account/(.+?)/?$', 'index.php?account_page=$matches[1]', 'top');
add_rewrite_tag( '%account_page%', '([^&]+)' );
}
}
add_action( 'plugins_loaded', array( new Your_Class, 'init' ) );
// Funzioni di attivazione una tantum
register_activation_hook( PATH_TO_PLUGIN_FILE, array( new Your_Class, 'flush_rules' ) );

puoi anche semplicemente usare add_rewrite_endpoint
, che genererà la regola per te e aggiungerà la query var in un solo passaggio. inoltre, se stai aggiungendo le tue regole di riscrittura, suggerisco la funzione add_rewrite_rule
invece di filtrare rewrite_rules_array
.

Grazie Milo, ho aggiornato il codice per usare add_rewrite_rule invece di filtrare l'array di riscrittura. Ho guardato add_rewrite_endpoint ma penso che add_rewrite_tag possa essere più adatto alle mie esigenze. Sembra che add_rewrite_endpoint sia utile principalmente se vuoi aggiungere argomenti extra alle riscritture esistenti di WP. Correggimi se sbaglio.
