web-dev-qa-db-fra.com

Belle façon de supprimer les variables GET avec PHP?

J'ai une chaîne avec une URL complète, y compris les variables GET. Quel est le meilleur moyen de supprimer les variables GET? Y a-t-il un bon moyen d'enlever un seul d'entre eux?

C'est un code qui fonctionne mais qui n'est pas très beau (je pense):

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

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

84
Jens Törnell

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

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

Voir à propos de strtok here .

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

Pour prendre une chaîne de caractère url + querystring et supprimer une seule variable (sans utiliser un remplacement de regex, ce qui peut être plus rapide dans certains cas), vous pouvez effectuer les opérations suivantes:

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 une seule variable pourrait ressembler à ceci:

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

Voici le minutage de quelques méthodes différentes, assurant que le chronométrage est réinitialisé entre les exécutions.

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

spectacles

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; 

strtok gagne et est de loin le plus petit code.

218
Justin

Que diriez-vous:

preg_replace('/\\?.*/', '', $str)
31
Gumbo

Si l'URL à partir de laquelle vous essayez de supprimer la chaîne de requête est l'URL actuelle du script PHP, vous pouvez utiliser l'une des méthodes précédemment mentionnées. Si vous ne disposez que d'une variable chaîne URL dans celui-ci et vous voulez effacer tout ce qui est passé après le "?" Que vous pouvez faire:

$pos = strpos($url, "?");
$url = substr($url, 0, $pos);
10
Matt Bridges

Inspiré par le commentaire de @MitMaro, j'ai rédigé un petit test de performances pour tester la rapidité des solutions de @Gumbo, @Matt Bridges et @justin dans la proposition suivante:

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; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12 ; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; rex: 0,11; ; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; expression rationnelle: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; regexp: 0,31; strpos: 0,18; 
 strtok: 0,12; exploser: 0,19; expression rationnelle: 0,31; strpos: 0,18; 

Résultat: @ justin's strtok est le plus rapide.

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

7
Scharrels

Une autre solution ... Je trouve cette fonction plus élégante, cela supprimera également le trailing "?" 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/>';
}

Est-ce que la sortie:

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

"Exécutez ces tests sur 3v4l

6
COil

Ne pourriez-vous pas utiliser les variables du serveur pour faire cela?

Ou est-ce que cela fonctionnerait ?:

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

Juste une pensée.

3
bobert

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

2
Scharrels
@list($url) = explode("?", $url, 2);
1
Rob Haswell

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

! Ebauche 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 cela serait bien de garder à portée de main pour les liens de pagination, etc.

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

À mon avis, le meilleur moyen serait le suivant:

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

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

0
Joshua Anderson

basename($_SERVER['REQUEST_URI']) retourne tout ce qui suit et incluant le '?',

Parfois, dans mon code, je n'ai besoin que de sections, alors séparez-le afin d'obtenir la valeur de ce dont j'ai besoin à la volée. Pas sûr de la vitesse d'exécution comparée à d'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;
0
Sidupac