2009-08-09 8 views
76

J'ai une chaîne avec une URL complète incluant les variables GET. Quel est le meilleur moyen de supprimer les variables GET? Existe-t-il un bon moyen de supprimer un seul d'entre eux?Belle façon de supprimer les variables GET avec PHP?

Ceci est un code qui fonctionne mais il est pas très beau (je pense):

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

Le code ci-dessus juste toutes les supprime variables GET. L'URL est dans mon cas générée à partir d'un CMS, donc je n'ai pas besoin d'informations sur les variables du serveur.

+1

Je voudrais rester avec ce que vous avez, sauf si la performance n'est pas un problème. La solution regex fournie par Gumbo va être aussi jolie que possible. – MitMaro

+0

Il n'a pas besoin d'être beau si ça va dans functions.php ou si vous cachez vos vilains bits, vous aurez seulement besoin de voir qs_build() pour l'appeler –

+0

Voici une façon de le faire via une belle fonction anonyme. http://stackoverflow.com/questions/4937478/strip-off-url-parameter-with-php/17287657#17287657 – doublejosh

Répondre

196

Ok, pour supprimer toutes les variables, la plus jolie est peut-être

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

Voir au sujet strtok here.

C'est le plus rapide (voir ci-dessous), et gère les URL sans '?' correctement.

Pour prendre une url + querystring et supprimez une variable (sans utiliser regex remplacer, ce qui peut être plus rapide dans certains cas), vous pourriez faire quelque chose comme:

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 regex remplacer pour supprimer un var simple pourrait ressembler à:

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

Heres les timings de quelques méthodes différentes, assurant le calendrier est remis à zéro inbetween fonctionne.

<?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; "; 

montre

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; 

gagne strtok, et est de loin le plus petit code.

+0

Ok, j'ai changé d'avis. Strook Way semble encore mieux. Les autres fonctions n'ont pas très bien fonctionné. J'ai essayé les fonctions sur ces variables get cbyear = 2013 & test = value et j'ai écrit echo removeqsvar ($ current_url, 'cbyear'); et a obtenu le résultat: amp; test = valeur –

+0

ah ouais ... l'expression rationnelle n'est pas complète - il faudra remplacer le délimiteur arrière et manquer le premier (écrit aveugle). La fonction plus longue devrait néanmoins fonctionner correctement. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $)/',' $ 1 ', $ url) devrait fonctionner – Justin

+2

+1 pour 'strtok', personne d'autre ne pensait de cela :) – knittl

2

Vous pouvez utiliser le server variables pour cela, par exemple $_SERVER['REQUEST_URI'], ou mieux: $_SERVER['PHP_SELF'].

+3

Cela suppose bien sûr que l'URL qu'il analyse est la page qui effectue l'analyse. – MitMaro

26

Que diriez-vous:

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

Certainement plus joli. Je me demande lequel ferait mieux cependant. +1 – MitMaro

+0

Cela m'a sauvé quelques rangs et pour moi c'est court et beau. Je vous remercie! –

+0

Cela vaut la peine d'être sur la liste; solution la plus courte. – Scharrels

7

Si l'URL que vous essayez de supprimer la chaîne de requête de l'URL est en cours du script PHP, vous pouvez utiliser l'une des méthodes mentionnées précédemment. Si vous avez juste une variable de chaîne avec une URL et que vous voulez enlever tout ce qui est passé? vous pouvez faire:

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

+1 parce que c'est la seule autre réponse ici qui répond à la question et fournit une alternative. – MitMaro

+1

Vous devez considérer que l'URL ne peut pas contenir un '?'. Votre code retournera alors une chaîne vide. – Gumbo

0

Que diriez-vous d'une fonction de réécrire la chaîne de requête en boucle à travers le tableau $ _GET

! esquisse d'une fonction appropriée

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); 
} 

Quelque chose comme ce serait bon de garder à portée de main pour les liens etc. paginations

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

Inspirée par le commentaire de @MitMaro, j'ai écrit un petit benchmark pour tester la vitesse de solutions de @Gumbo, ponts et @justin la @ Matt proposition dans la question:

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: @ justin's strtok est le plus rapide.

Note: testé sur un système Debian Lenny local avec Apache2 et PHP5.

+0

temps d'exécution regexp: 0.14591598510742 secondes; exploser le temps d'exécution: 0.07137393951416 secondes; temps d'exécution de strpos: 0.080883026123047 secondes; temps d'exécution tok: 0,042459011077881 secondes; – Justin

+0

Très bien! Je pense que la vitesse est importante. Ce n'est pas la seule chose qui va arriver. Une application Web pourrait avoir des centaines de fonctions. "Tout est dans les détails". Merci, votez! –

+0

Justin, merci.Le script est maintenant nettoyé et prend en compte votre solution. – Scharrels

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

Vous ne pouviez pas utiliser les variables de serveur pour faire cela?

Ou serait-ce travail ?:

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

Juste une pensée.

0

basename($_SERVER['REQUEST_URI']) retourne tout ce qui suit et y compris le « ? »,

Dans mon code parfois je besoin que les sections, donc séparer dehors je peux obtenir la valeur de ce que je dois à la volée. Je ne suis pas sûr de la vitesse de la performance par rapport aux autres méthodes, mais c'est vraiment utile pour moi.

$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

Une autre solution ... Je trouve cette fonction plus élégante, elle supprimera également le «? si la clé à supprimer est la seule dans la chaîne de requête.

/** 
* 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; 
} 

Tests:

$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/>'; 
} 

Affichera:

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

À mon avis, la meilleure façon serait ceci:

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

Il vérifie s'il existe un paramètre GET 'i' et le supprime s'il y en a un.