webentwicklung-frage-antwort-db.com.de

Schöne Möglichkeit, GET-Variablen mit PHP zu entfernen?

Ich habe eine Zeichenfolge mit einer vollständigen URL einschließlich GET-Variablen. Was ist der beste Weg, um die GET-Variablen zu entfernen? Gibt es eine gute Möglichkeit, nur einen davon zu entfernen?

Dies ist ein Code, der funktioniert, aber nicht sehr schön ist (denke ich):

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

Der obige Code entfernt nur alle GET-Variablen. Die URL wird in meinem Fall von einem CMS generiert, sodass ich keine Informationen zu Servervariablen benötige.

84
Jens Törnell

Ok, um alle Variablen zu entfernen, ist vielleicht die schönste

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

Siehe ungefähr strtok hier .

Es ist das schnellste (siehe unten) und verarbeitet URLs ohne '?' richtig.

Um eine URL + Abfragezeichenfolge zu verwenden und nur eine Variable zu entfernen (ohne einen regulären Ausdruck zu verwenden, der in manchen Fällen schneller sein kann), können Sie Folgendes tun:

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

Ein regulärer Ausdruck zum Entfernen einer einzelnen Variable könnte folgendermaßen aussehen:

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

Hier sind die Timings einiger verschiedener Methoden, die sicherstellen, dass das Timing zwischen den Läufen zurückgesetzt wird.

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

zeigt an

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 gewinnt und ist mit Abstand der kleinste Code.

218
Justin

Wie wäre es mit:

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

Wenn die URL, von der Sie die Abfragezeichenfolge entfernen möchten, die aktuelle URL des Skripts PHP ist, können Sie eine der zuvor genannten Methoden verwenden. Wenn Sie nur eine Zeichenfolgenvariable mit einem haben URL und Sie möchten alles hinter dem '?' Entfernen, was Sie tun können:

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

Inspiriert durch den Kommentar von @MitMaro habe ich einen kleinen Benchmark geschrieben, um die Geschwindigkeit der Lösungen von @Gumbo, @Matt Bridges und @ den Vorschlag in der Frage zu testen:

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; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12 ; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31 ; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 
 Strtok: 0,12; Explosion: 0,19; Regexp: 0,31; Strpos: 0,18; 

Ergebnis: @ justin's strtok ist am schnellsten.

Hinweis: Getestet auf einem lokalen Debian Lenny-System mit Apache2 und PHP5.

7
Scharrels

Eine andere Lösung ... Ich finde diese Funktion eleganter, es wird auch das nachfolgende '?' wenn der zu entfernende Schlüssel der einzige in der Abfragezeichenfolge ist.

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

Wird ausgeben:

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

"Führen Sie diese Tests mit 3v4l durch

6
COil

Könnten Sie nicht die Servervariablen verwenden, um dies zu tun?

Oder würde das funktionieren ?:

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

Nur ein Gedanke.

3
bobert

Sie können dazu die Servervariablen verwenden, zum Beispiel $_SERVER['REQUEST_URI'] oder noch besser: $_SERVER['PHP_SELF'].

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

Wie wäre es mit einer Funktion zum Umschreiben der Abfragezeichenfolge durch Durchlaufen des Arrays $ _GET

! Grobe Darstellung einer geeigneten Funktion

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

So etwas wäre gut, um für Paginierungslinks usw. griffbereit zu sein.

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

Meiner Meinung nach wäre der beste Weg:

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

Es prüft, ob es einen 'i' GET-Parameter gibt, und entfernt ihn, falls vorhanden.

0
Joshua Anderson

basename($_SERVER['REQUEST_URI']) gibt alles nach und einschließlich des '?'

In meinem Code benötige ich manchmal nur Abschnitte. Trennen Sie diese, damit ich den Wert dessen, was ich brauche, sofort abrufen kann. Ich bin nicht sicher, wie schnell die Leistung im Vergleich zu anderen Methoden ist, aber es ist wirklich nützlich für mich.

$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