2009-08-09 14 views
76

Ho una stringa con un URL completo che include le variabili GET. Qual è il modo migliore per rimuovere le variabili GET? C'è un buon modo per rimuovere solo uno di loro?Bel modo di rimuovere le variabili GET con PHP?

Si tratta di un codice che funziona, ma non è molto bello (credo):

$current_url = explode('?', $current_url); 
echo $current_url[0]; 

Il codice di cui sopra rimuove solo tutte le variabili GET. Nel mio caso l'URL è generato da un CMS, quindi non ho bisogno di informazioni sulle variabili del server.

+1

Vorrei attenermi a ciò che si ha a meno che le prestazioni non siano un problema. La soluzione regex fornita da Gumbo sarà molto carina. – MitMaro

+0

Non ha bisogno di essere bello se sta andando in functions.php o ovunque tu nascondi i tuoi brutti bit, devi solo vedere qs_build() per chiamarlo –

+0

Ecco un modo per farlo tramite una bella funzione anonima. http://stackoverflow.com/questions/4937478/strip-off-url-parameter-with-php/17287657#17287657 – doublejosh

risposta

196

Ok, per rimuovere tutte le variabili, forse la più bella è

$url = strtok($url, '?'); 

Vedere Informazioni strtok here.

È il più veloce (vedi sotto) e gestisce gli URL senza '?' propriamente.

Per scattare un'url + querystring e rimuovere una sola variabile (senza utilizzare un'espressione regolare sostituzione, che può essere più veloce in alcuni casi), si potrebbe fare qualcosa di simile:

function removeqsvar($url, $varname) { 
    list($urlpart, $qspart) = array_pad(explode('?', $url), 2, ''); 
    parse_str($qspart, $qsvars); 
    @unset($qsvars[$varname]); 
    $newqs = http_build_query($qsvars); 
    return $urlpart . '?' . $newqs; 
} 

Un'espressione regolare sostituzione per rimuovere un singolo var potrebbe essere simile:

function removeqsvar($url, $varname) { 
    return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url); 
} 

Heres i tempi di alcuni metodi differenti, garantendo tempi viene azzerato inbetween piste.

<?php 

$number_of_tests = 40000; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 

for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    preg_replace('/\\?.*/', '', $str); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "regexp execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $str = explode('?', $str); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "explode execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $qPos = strpos($str, "?"); 
    $url_without_query_string = substr($str, 0, $qPos); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "strpos execution time: ".$totaltime." seconds; "; 

$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$starttime = $mtime; 
for($i = 0; $i < $number_of_tests; $i++){ 
    $str = "http://www.example.com?test=test"; 
    $url_without_query_string = strtok($str, '?'); 
} 
$mtime = microtime(); 
$mtime = explode(" ",$mtime); 
$mtime = $mtime[1] + $mtime[0]; 
$endtime = $mtime; 
$totaltime = ($endtime - $starttime); 
echo "tok execution time: ".$totaltime." seconds; "; 

mostra

regexp execution time: 0.14604902267456 seconds; explode execution time: 0.068033933639526 seconds; strpos execution time: 0.064775943756104 seconds; tok execution time: 0.045819044113159 seconds; 
regexp execution time: 0.1408839225769 seconds; explode execution time: 0.06751012802124 seconds; strpos execution time: 0.064877986907959 seconds; tok execution time: 0.047760963439941 seconds; 
regexp execution time: 0.14162802696228 seconds; explode execution time: 0.065848112106323 seconds; strpos execution time: 0.064821004867554 seconds; tok execution time: 0.041788101196289 seconds; 
regexp execution time: 0.14043688774109 seconds; explode execution time: 0.066350221633911 seconds; strpos execution time: 0.066242933273315 seconds; tok execution time: 0.041517972946167 seconds; 
regexp execution time: 0.14228296279907 seconds; explode execution time: 0.06665301322937 seconds; strpos execution time: 0.063700199127197 seconds; tok execution time: 0.041836977005005 seconds; 

vittorie strtok, ed è di gran lunga il più piccolo codice.

+0

Ok, ho cambiato idea. modo strtok sembra ancora meglio. Le altre funzioni non hanno funzionato così bene. Ho provato le funzioni su queste ottenere le variabili? Cbyear = 2013 & test = value e ha scritto echo removeqsvar ($ current_url, 'cbyear'); e ha ottenuto il risultato: amp; test = valore –

+0

ah sì ... la regex non è completa - sarà necessario sostituire il delimitatore finale e mancare quello principale (lo ha scritto cieco). La funzione più lunga dovrebbe comunque funzionare bene. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $)/',' $ 1 ', $ url) dovrebbe funzionare – Justin

+2

+1 per 'strtok', nessun altro pensato di quello :) – knittl

2

È possibile utilizzare server variables per questo, ad esempio $_SERVER['REQUEST_URI'] o anche meglio: $_SERVER['PHP_SELF'].

+3

Ciò presuppone naturalmente che l'url che sta analizzando sia la pagina che esegue l'analisi. – MitMaro

26

ne dite:

preg_replace('/\\?.*/', '', $str) 
+1

Decisamente più carino. Mi chiedo quale si comporterebbe meglio però. +1 – MitMaro

+0

Questo mi ha salvato alcune righe e per me questo è breve e bello. Grazie! –

+0

vale ancora un upvote; soluzione più corta. – Scharrels

7

Se l'URL che si sta tentando di rimuovere la stringa di query da è l'attuale URL dello script PHP, è possibile utilizzare uno dei metodi menzionati in precedenza. Se hai solo una variabile di stringa con un URL e vuoi rimuovere tutti i "?" si può fare:

$pos = strpos($url, "?"); 
$url = substr($url, 0, $pos); 
+0

+1 perché è l'unica altra risposta qui che risponde alla domanda e fornisce un'alternativa. – MitMaro

+1

Dovresti considerare che l'URL potrebbe non contenere un '?'. Il tuo codice restituirà quindi una stringa vuota. – Gumbo

0

Che ne dite di una funzione per riscrivere la query string dal loop attraverso il $ _GET serie

! abbozzo di una opportuna funzione

function query_string_exclude($exclude, $subject = $_GET, $array_prefix=''){ 
    $query_params = array; 
    foreach($subject as $key=>$var){ 
     if(!in_array($key,$exclude)){ 
     if(is_array($var)){ //recursive call into sub array 
      $query_params[] = query_string_exclude($exclude, $var, $array_prefix.'['.$key.']'); 
     }else{ 
      $query_params[] = (!empty($array_prefix)?$array_prefix.'['.$key.']':$key).'='.$var; 
     } 
     } 
    } 

    return implode('&',$query_params); 
} 

Qualcosa di simile a questo sarebbe bene tenere a portata di mano per i link di paginazione ecc

<a href="?p=3&<?= query_string_exclude(array('p')) ?>" title="Click for page 3">Page 3</a> 
7

Ispirato dal commento di @MitMaro, ho scritto un piccolo punto di riferimento per testare la velocità di soluzioni di @Gumbo, @ Matt Ponti e @justin la proposta nella domanda:

function teststrtok($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $str = strtok($str,'?'); 
    } 
} 
function testexplode($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $str = explode('?', $str); 
    } 
} 
function testregexp($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     preg_replace('/\\?.*/', '', $str); 
    } 
} 
function teststrpos($number_of_tests){ 
    for($i = 0; $i < $number_of_tests; $i++){ 
     $str = "http://www.example.com?test=test"; 
     $qPos = strpos($str, "?"); 
     $url_without_query_string = substr($str, 0, $qPos); 
    } 
} 

$number_of_runs = 10; 
for($runs = 0; $runs < $number_of_runs; $runs++){ 

    $number_of_tests = 40000; 
    $functions = array("strtok", "explode", "regexp", "strpos"); 
    foreach($functions as $func){ 
    $starttime = microtime(true); 
    call_user_func("test".$func, $number_of_tests); 
    echo $func.": ". sprintf("%0.2f",microtime(true) - $starttime).";"; 
    } 
    echo "<br />"; 
} 
 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 
strtok: 0.12;explode: 0.19;regexp: 0.31;strpos: 0.18; 

Res ult: @ justto's strtok è il più veloce.

Nota: testato su un sistema Debian Lenny locale con Apache2 e PHP5.

+0

tempo di esecuzione regexp: 0,14591598510742 secondi; esplode tempo di esecuzione: 0,07137393951416 secondi; tempo di esecuzione dello strpos: 0,080883026123047 secondi; tempo di esecuzione tok: 0,042459011077881 secondi; – Justin

+0

Molto bello! Penso che la velocità sia importante. Non è l'unica cosa che succederà. Un'applicazione Web potrebbe avere centinaia di funzioni. "È tutto nei dettagli". Grazie, vota! –

+0

Justin, grazie.Lo script è ora ripulito e tiene conto della tua soluzione. – Scharrels

0
@list($url) = explode("?", $url, 2); 
2

Non potresti utilizzare le variabili del server per fare ciò?

O sarebbe questo lavoro ?:

unset($_GET['page']); 
$url = $_SERVER['SCRIPT_NAME'] ."?".http_build_query($_GET); 

Solo un pensiero.

0

basename($_SERVER['REQUEST_URI']) restituisce tutto dopo e tra cui il '?',

Nel mio codice a volte ho bisogno solo le sezioni, in modo da separare fuori in modo da poter ottenere il valore di quello che mi serve al volo. Non sono sicuro della velocità delle prestazioni rispetto ad altri metodi, ma è davvero utile per me.

$urlprotocol = 'http'; if ($_SERVER["HTTPS"] == "on") {$urlprotocol .= "s";} $urlprotocol .= "://"; 
$urldomain = $_SERVER["SERVER_NAME"]; 
$urluri = $_SERVER['REQUEST_URI']; 
$urlvars = basename($urluri); 
$urlpath = str_replace($urlvars,"",$urluri); 

$urlfull = $urlprotocol . $urldomain . $urlpath . $urlvars; 
5

Un'altra soluzione ... Trovo questa funzione più elegante, sarà anche rimuovere il finale '?' se la chiave da rimuovere è l'unica nella stringa di query.

/** 
* Remove a query string parameter from an URL. 
* 
* @param string $url 
* @param string $varname 
* 
* @return string 
*/ 
function removeQueryStringParameter($url, $varname) 
{ 
    $parsedUrl = parse_url($url); 
    $query = array(); 

    if (isset($parsedUrl['query'])) { 
     parse_str($parsedUrl['query'], $query); 
     unset($query[$varname]); 
    } 

    $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : ''; 
    $query = !empty($query) ? '?'. http_build_query($query) : ''; 

    return $parsedUrl['scheme']. '://'. $parsedUrl['host']. $path. $query; 
} 

Test:

$urls = array(
    'http://www.example.com?test=test', 
    'http://www.example.com?bar=foo&test=test2&foo2=dooh', 
    'http://www.example.com', 
    'http://www.example.com?foo=bar', 
    'http://www.example.com/test/no-empty-path/?foo=bar&test=test5', 
    'https://www.example.com/test/test.test?test=test6', 
); 

foreach ($urls as $url) { 
    echo $url. '<br/>'; 
    echo removeQueryStringParameter($url, 'test'). '<br/><br/>'; 
} 

visualizzerà:

http://www.example.com?test=test 
http://www.example.com 

http://www.example.com?bar=foo&test=test2&foo2=dooh 
http://www.example.com?bar=foo&foo2=dooh 

http://www.example.com 
http://www.example.com 

http://www.example.com?foo=bar 
http://www.example.com?foo=bar 

http://www.example.com/test/no-empty-path/?foo=bar&test=test5 
http://www.example.com/test/no-empty-path/?foo=bar 

https://www.example.com/test/test.test?test=test6 
https://www.example.com/test/test.test 

» Run these tests on 3v4l

0

A mio parere, il modo migliore sarebbe questo:

<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?> 

Controlla se esiste un parametro i 'GET e lo rimuove se esiste.

Problemi correlati