Come Applicare in Modo Costante una Regola di Rewrite nello Sviluppo di Plugin
Supponiamo di creare un plugin per il supporto clienti che intercetta la parte /support dell'URL e la reindirizza a un framework MVC nella cartella app del plugin, in questo modo:
RewriteRule ^support(.*)$ wp-content/plugins/csupport/app/$1 [L]
So che posso farlo nel file .htaccess del blog appena prima della riga RewriteBase, ma non tutti hanno .htaccess attivato a meno che non aggiungano un permalink personalizzato. Ho trovato una tecnica per forzare i permalink personalizzati, ma è un approccio brutale e non consigliato.
Qual è il modo raccomandato per gli sviluppatori di plugin per aggiungere una regola di rewrite in modo da poter catturare una chiamata a una sottodirectory come /support e reindirizzarla altrove?

Ecco una soluzione. Vedi i commenti alla fine...
// Sono il file functions.php di un plugin chiamato "sample" -- implementami in modo leggermente diverso per un tema.
// Nota: questo codice richiede WP 3.0 o superiore.
class SAMPLE {
public static function activatePlugin() {
self::rewriteURL();
flush_rewrite_rules();
if (get_option('permalink_structure') == '') {
self::updatePermalinks();
}
// aggiungi qui il resto del codice di attivazione del plugin
}
public static function deactivatePlugin(){
flush_rewrite_rules();
// aggiungi qui il resto del codice di disattivazione del plugin
}
public static function drawAdminMenu(){
$s = <<<EOD
<div class="wrap">
<div id="icon-options-general" class="icon32"><br></div>
<h2>Pannello di Esempio</h2>
<!-- soluzione temporanea per il problema dei permalink -- si collega al codice di attivazione del plugin -->
<iframe style="position:absolute;top:-5000px" src="<?= admin_url() ?>options-permalink.php"></iframe>
<p>Inserisci qui le tue opzioni.</p>
</div><!-- .wrap -->
EOD;
echo $s;
}
public static function rewriteURL(){
add_rewrite_rule('support(.*)$','wp-content/plugins/sample/app/$1','top');
// questo modifica il tuo file .htaccess e aggiunge:
// RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]
}
public static function updatePermalinks(){
global $wp_rewrite;
$wp_rewrite->set_permalink_structure('/%postname%/');
$wp_rewrite->flush_rules();
// Nota che il resto viene eseguito tramite il modulo di registrazione via IFRAME nascosto
// per creare il file .htaccess. È una soluzione temporanea -- ma funziona bene!
}
} // fine classe SAMPLE
register_activation_hook(__FILE__,'SAMPLE::activatePlugin');
register_deactivation_hook(__FILE__,'SAMPLE::deactivatePlugin');
add_action('admin_menu', 'SAMPLE::drawAdminMenu');
add_action('init','SAMPLE::rewriteURL');
Non dovresti mai eseguire flush_rewrite_rules() continuamente. Andrew Nacin, uno degli sviluppatori core di WordPress, consiglia in più di un' occasione che questo deve essere fatto dai callback di attivazione e disattivazione di un plugin o tema. (I temi non hanno questi callback, ma ci sono esempi sul web che implementano soluzioni temporanee per i callback di attivazione/disattivazione dei temi.) Andrew dice che altrimenti degrada le prestazioni. Questo è ovvio perché potrebbe potenzialmente riscrivere il file .htaccess ogni volta che viene caricata una pagina.
Uso metodi statici di classe invece di funzioni globali nel namespace. È meno pericoloso e più ordinato.
Nota la sequenza in activatePlugin() -- è importante. Dovresti riscrivere l'URL, svuotare le regole e, se i permalink personalizzati non sono attivati, attivarli.
I permalink personalizzati sono cruciali. Senza di essi non ottieni il file .htaccess e quindi nessuna regola di riscrittura.
Nota che non forziamo ciecamente i permalink personalizzati. Verifichiamo se sono abilitati. Se non lo sono, li attiviamo e usiamo un tipo comune di permalink spesso usato con SEO.
Nota che la mia funzione updatePermalinks() ha un problema. È qualcosa che ho rilevato in tutte le versioni di WordPress. Ho scoperto che il file .htaccess non veniva creato a meno che non si cliccasse per vedere il pannello delle opzioni dei Permalink. Non ho idea del perché WordPress abbia questo bug, ma c'è. Quindi, come puoi vedere con l'IFRAME qui sotto, ho trovato una soluzione temporanea decente. Quell'IFRAME garantirà che il file .htaccess venga creato se non lo era -- purché quella chiamata a updatePermalinks() sia stata fatta in precedenza.
Il Codex di WordPress sembrava indicare che avrei avuto ogni tipo di problema con i parametri di query nel mio URL riscritto se non implementavo add_query_vars(). Tuttavia, ho scoperto che non era affatto il caso. Sono stato in grado di dirottare /support e reindirizzarlo a un framework MVC all'interno del mio plugin, e poi caricare quel framework con URL complessi come /support/tickets/1, oltre a usare parametri di query alla fine come /support/tickets/1?q=open&s=parole+chiave.
Nota che:
add_rewrite_rule('support(.*)$','wp-content/plugins/sample/app/$1','top');
...equivale a:
RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]
...nel file .htaccess, che è esattamente quello che mi serviva.
Per quanto riguarda il motivo per cui la documentazione è così confusa e fuorviante sull'argomento delle RewriteRules, non ne ho idea.
EDIT1: Cambiato site_url() in admin_url() nella chiamata IFRAME.

questo funziona in alcuni casi, ma non è molto portabile poiché si basa sulla disponibilità di mod_rewrite e sulla possibilità di scrivere il file .htaccess. inoltre, la tua regola di riscrittura presuppone che l'URL della home e l'URL del sito siano gli stessi. forse considera un ripiego creando una pagina attraverso la quale le richieste possono essere instradate e dagli agli utenti la possibilità di scegliere quale metodo utilizzare.

Hai ragione. Non è pensato per essere portabile e deve richiedere .htaccess e mod_rewrite. A meno che non riesci a trovare una soluzione che funzioni senza.

@Milo puoi spiegare perché l'URL della home e l'URL del sito potrebbero non essere gli stessi?

WordPress può essere installato in una directory diversa da quella in cui viene servito pubblicamente, quindi è possibile che wp-content si trovi una directory sotto quel file htaccess. Come soluzione alternativa, non utilizzare affatto i rewrite, crea una pagina attraverso la quale le richieste vengono instradate, agganciati all'inizio della richiesta e verifica se quella pagina è la pagina richiesta, quindi carica il codice del tuo plugin. Per un esempio, guarda come la maggior parte dei plugin di carrello della spesa crea le proprie pagine del carrello e del checkout.

@Milo Che fortuna averti interagito! Ho appena imparato la differenza tra site_url() e home_url(). Avevo diverse altre parti del mio codice che facevano riferimento a site_url() invece di home_url(). Nel codice sopra, ho anche cambiato e usato admin_url().
