Riscrivere un numero arbitrario di segmenti di percorso per interrogare i parametri

Ho questa regola .htaccess:

RewriteRule viewshoplatest/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/(.*)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16 

Dovrebbe mappare un URL come questo:

 http://www.veepiz.com/viewshoplatest/start/10/end/10/filter/0/ownerid/0/sortby/date/sortdir/DESC/cat/0/scat/0/ 

a questa:

 http://www.veepiz.com/viewshoplatest.php?start=0&end=10&filter=0&ownerid=0&sortby=date&sortdir=DESC&cat=0&scat=0 

Quando faccio clic sul link e $_GET variabili $_GET ottengo questo:

 Array ( [start] => 10 [end] => 10 [filter] => 0 [ownerid] => 0 [sortby] => start0 [start1] => start2 [start3] => start4 [start5] => start6 ) 

Qualche idea sul perché si sta comportando male?


Ok ho risolto questo riscrivendo la regola a

 RewriteRule viewshoplatest/start/(.*)/end/(.*)/filter/(.*)/ownerid/(.*)/sortby/(.*)/sortdir/(.*)/cat/(.*)/scat/(.*)/$ /viewshoplatest.php?start=$1&end=$2&filter=$3&ownerid=$4&sortby=$5&sortdir=$6&cat=$7&scat=$8 

Prima di tutto: non dovresti usare .* Se puoi essere più specifico, come in questo caso [^/]+ . Perché multipli .* Possono causare immensi backtracking. Così:

 RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/$ /viewshoplatest.php?$1=$2&$3=$4&$5=$6&$7=$8&$9=$10&$11=$12&$13=$14&$15=$16 

È ansible utilizzare un Take come RegexBuddy per vedere la differenza nel modo in cui vengono elaborate queste espressioni regolari.

Ma poiché mod_rewrite consente solo di fare riferimento ai primi nove gruppi (vedi la risposta di Tim ), potresti usare un approccio iterativo e processare un parametro alla volta:

 RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]+/[^/]+/.*)$ /viewshoplatest/$3?$1=$2 [QSA,N] RewriteRule ^viewshoplatest/([^/]+)/([^/]+)/([^/]*)/?$ /viewshoplatest.php?$1=$2&$3 [QSA,L] 

La prima regola elaborerà una coppia di parametri alla volta (tranne l’ultima coppia) aggiungendola a quelle già esistenti (vedere il flag QSA ) e quindi riavvia il processo di riscrittura senza incrementare il contatore interno di ricorsione (vedi N flag). La seconda regola riscriverà quindi l’ultima coppia di parametri (o solo il nome) e terminerà l’iterazione.

Ma dal momento che l’utilizzo della bandiera N potrebbe essere pericoloso in quanto può causare una ricorsione infinita, è ansible utilizzare anche PHP per analizzare il percorso richiesto:

 $_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $segments = implode('/', trim($_SERVER['REQUEST_URI_PATH'], '/')); array_shift($segments); // remove path prefix "/viewshoplatest" for ($i=0, $n=count($segments); $i<$n; ) { $_GET[rawurldecode($segments[$i++])] = ($i < $n) ? rawurldecode($segments[$i++]) : null; } 

Ora hai solo bisogno di questa regola per passare la richiesta attraverso:

 RewriteRule ^viewshoplatest(/|$) /viewshoplatest.php [L] 

Solo per approfondire ciò che hai scoperto, puoi definire solo nove gruppi da utilizzare come backreferences, motivo per cui è in genere un’idea migliore per riscrivere una stringa sans-query dello script e fare in modo che lo script esamini REQUEST_URI nei casi in cui avrai un sacco di dati da analizzare.

Dalla documentazione :

I riferimenti indietro sono identificatori del modulo $ N (N = 0..9), che sarà sostituito dal contenuto del gruppo N ° del modello abbinato

$0 è l’intero schema abbinato, che ti dà i restanti nove numeri con cui lavorare. Qualsiasi numero più alto viene considerato come un backreference seguito da alcuni caratteri numerici letterali.