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.
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.
Que diriez-vous:
preg_replace('/\\?.*/', '', $str)
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);
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.
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
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.
Vous pouvez utiliser le variables serveur pour cela, par exemple $_SERVER['REQUEST_URI']
ou mieux encore: $_SERVER['PHP_SELF']
.
@list($url) = explode("?", $url, 2);
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>
À 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.
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;