Percorso personalizzato per plugin in WordPress

10 lug 2012, 22:14:25
Visualizzazioni: 23K
Voti: 16

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

0
Tutte le risposte alla domanda 2
4
16

Devi fare tre cose importanti:

  1. Creare una regola di riscrittura personalizzata per trasformare parti dell'URI in valori passati a index.php.
  2. Aggiungere myroute e myargument alla whitelist delle variabili di query di WordPress, in modo che WordPress non le ignori quando compaiono in una stringa di query.
  3. 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.

11 lug 2012 03:28:19
Commenti

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.

emc emc
25 feb 2014 19:42:52

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

eddiemoya eddiemoya
3 mar 2014 21:37:13

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?

Matt Keys Matt Keys
21 set 2014 13:36:17

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

Imran Zahoor Imran Zahoor
12 set 2015 23:15:56
3

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' ) );
24 set 2014 02:14:05
Commenti

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.

Milo Milo
24 set 2014 02:31:05

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.

Matt Keys Matt Keys
24 set 2014 03:03:30

Mi piace l'approccio orientato agli oggetti. Troppi sviluppatori WP ancora non sanno come usare la OOP. Grazie per cercare di ripristinare la mia fiducia negli sviluppatori PHP. ;)

Arvid Arvid
19 feb 2018 19:36:36