2011-07-17 11 views
6

ho attualmente il lavoro Mod Rewrite Regex:Mod Rewrite Regex - Più Lookaheads negativi

RewriteEngine On 
RewriteCond %{QUERY_STRING} ^(.*)$ 
RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(.+)) $1?$2=$3&%1 [L] 

Che regex prende il seguente URL e la trasforma in l'URL immediatamente sotto:

www.site.com/cmd1/param/cmd2/param2/stillparam2 e di trasformarlo in www.site.com/index.php?cmd1=param&cmd2=param2/stillparam2

che funziona bene, ma vorrei anche creare un altro asserzione lookahead negativo per garantire che un blocco di URL - vale a dire un param /texthere/ - non include un carattere di sottolineatura. Potrebbe apparire una stringa non valida: www.test.com/cmd/thing/getparam_valuehere; la regex dovrebbe analizzare lo cmd/thing come coppia chiave e valore e ignorare il resto della stringa. Poi scriverò anche un altro RewriteRule per avere il blocco dell'URL con il trattino basso in esso aggiunto come un altro parametro URL. La seguente traduzione URL sarebbe verificato:

www.test.com/cmd/param1/cmd2/directory/param2/sortorder_5 
www.test.com?cmd=param1&cmd2=directory/param2&sortorder=5 

Si prega di farmi sapere se non sono stato abbastanza chiaro. Qualsiasi aiuto sarebbe grande.

NB: Ho provato con un lookahead negativo annidato all'interno di quello già presente - (?!(?!)) - e provato con un | su due lookaheads negativi, ma né soluzioni lavorato. Ho pensato che forse qualcos'altro era fondamentalmente sbagliato?

Grazie a tutti.

Edit: Ho anche provato il seguente - che ho davvero pensato avrebbe funzionato (ma ovviamente, non ha!)

RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(?![.+]*(?:_)[.+]*)(.+)) $1?$2=$3&%1 [L] 

che fa la seguente:

www.test.com/cmd/param1/sortorder_1/ traduce in www.test.com?cmd=param1/sortorder_1/

Quando invece dovrebbe diventare: www.test.com?cmd=param1&sortorder=2/. La regola per tradurre /sortorder_2/ in &sortorder=2 non è stata ancora creata, ma si può sperare di vedere cosa intendo).

+2

_Lookbehinds_ deve essere di lunghezza costante, i lookahead di lunghezza variabile devono essere OK. – MRAB

+0

Sì, sicuramente qui vengono utilizzati solo lookahead negativi. Grazie per la risposta! – Pete171

+0

Ho anche provato quanto segue: 'RewriteRule^(. * /)? ((?: cmd) [^ /] *)/((?! (?: [A-Za-z0-9]) * _ + (?: [A-Za-z0-9]) *) (. +)) $ 1? $ 2 = $ 3 e% 1 [L] '. Qui, ho rimosso il lookahead negativo (funzionante) originale e l'ho sostituito con un altro che dovrebbe garantire che un trattino basso non sia presente in un blocco URL prima di includerlo come parte di un parametro. Questo non ha funzionato e ha generato la seguente stringa di query: 'cmd = chiave/to/comando/valore_qui/sortorder_5 /' Era mia intenzione fermarsi a '/ value_here /' in modo da poter convalidare lookahead negativo trova il segmento di sottolineatura correttamente. Senza fortuna. – Pete171

risposta

1

Dopo circa quattro giorni di sperimentazione, ho trovato una soluzione leggermente diversa da quella che mi aspettavo originariamente di trovare. Ho semplicemente rimosso tutta la manipolazione effettiva dell'URL nel mio file index.php e ho indirizzato tutte le richieste da lì. Ecco il mio (molto più pulito).file .htaccess:

Options +FollowSymlinks 
RewriteEngine On 
RewriteCond %{QUERY_STRING} (.*) 
RewriteRule (.*) index.php?path=$1 [QSA,L] 

ed ecco il blocco di codice che ho usato per analizzare l'URL immesso:

preg_match_all ('|/([A-Za-Z0-9] +) ((? ! /) [A-Za-z0-9-.] *) | ', $ _GET [' percorso '], $ corrisponde);

 // Remove all '$_GET' parameters from the actual $_GET superglobal: 
     foreach($matches[0] as $k => $v) { 
      $search = '/' . substr($v, 1); 
      $_GET['path'] = str_replace($search, '', $_GET['path'], $count); 
     } 

     // Add $_GET params to URL args 
     for ($i = 0; $i < count($matches[1]); $i++) { 
      self::$get_arguments[$matches[1][$i]] = $matches[2][$i]; 
     } 

     // Retrieve all 'cmd' properties from the URL and create an array with them: 
     preg_match_all('~(cmd[0-9]*)/(.+?)(?=(?:cmd)|(?:\z))~', $_GET['path'], $matches); 

     if (isset($matches[1][0])) { 
      return self::$url_arguments = array_combine($matches[1], $matches[2]); 

su un URL simile a questo:

http://localhost/frame_with_cms/frame/www/cmd/one/cmd2/two/cmd3/three/cmd4/four/getparam_valuepart1_valuepart2/cmd5/five/ 

Produce con successo queste matrici distinte che ho poi usare per gestire le richieste:

Array 
(
    [getparam] => valuepart1_valuepart2 
) 
Array 
(
    [cmd] => one/ 
    [cmd2] => two/ 
    [cmd3] => three/ 
    [cmd4] => four/ 
    [cmd5] => five/ 
) 

Grazie a tutti coloro che hanno preso il tempo di leggere e rispondi.

+0

Devo ammettere che il mio primo pensiero è stato, perché farlo in un file .htaccess. Tuttavia, questa risposta non è davvero una soluzione per la tua domanda, dati i vincoli. – fncomp

0

Non sarebbe più semplice mantenere la regola di lavoro e riscrivere il valore param_value nella stringa di query prima della regola corrente?

Qualcosa di simile

RewriteRule ^(.*)?/([^_/]+)_([^/]+)/ $1/?$2=$3 [N,QSA]

dovrebbe aggiungere tutti/param_value/parti in nella querystring come param = value.

Fare attenzione utilizzando la bandiera N, si potrebbe finire con un ciclo infinito.

+0

Ci proverò dopo il lavoro e posterò il risultato. Grazie per la risposta! – Pete171

+0

@CharStringIncluse la precedente regola di riscrittura prima della prima e ho ottenuto un ciclo infinito! Grazie per la risposta lo stesso, molto apprezzato. – Pete171