Un bel modo per rimuovere le variabili GET con PHP?


92

Ho una stringa con un URL completo che include le variabili GET. Qual è il modo migliore per rimuovere le variabili GET? C'è un modo carino per rimuoverne solo uno?

Questo è un codice che funziona ma non è molto bello (credo):

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

Il codice sopra rimuove solo tutte le variabili GET. L'URL è nel mio caso generato da un CMS quindi non ho bisogno di alcuna informazione sulle variabili del server.


1
Rimango fedele a quello che hai a meno che le prestazioni non siano un problema. La soluzione regex fornita da Gumbo sarà la più carina possibile.
MitMaro

Non ha bisogno di essere bello se sta andando in functions.php o dovunque nascondi i tuoi brutti pezzi, dovrai solo vedere qs_build () per chiamarlo
Punto interrogativo

Ecco un modo per farlo tramite una bella funzione anonima. stackoverflow.com/questions/4937478/...
doublejosh

E il frammento di URL? Le soluzioni che vedo sotto eliminano tutte anche il frammento, proprio come fa il tuo codice.
Marten Koetsier

Risposte:


232

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

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

Vedi strtokqui .

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

Per prendere un URL + una stringa di query e rimuovere solo una variabile (senza utilizzare una sostituzione regex, che in alcuni casi potrebbe essere più veloce), potresti fare qualcosa come:

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

Una regex replace per rimuovere una singola var potrebbe essere simile a:

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

Ecco i tempi di alcuni metodi diversi, assicurando che i tempi vengano ripristinati tra le corse.

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

Spettacoli

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 vince ed è di gran lunga il codice più piccolo.


Ok, ho cambiato idea. il modo strtok sembra ancora migliore. Le altre funzioni non funzionavano così bene. Ho provato le funzioni su queste variabili get? Cbyear = 2013 & test = value e ho scritto echo removeqsvar ($ current_url, 'cbyear'); e ho ottenuto il risultato: amp; test = value
Jens Törnell

ah sì ... la regex non è completa - dovrà sostituire il delimitatore finale e perdere quello iniziale (scritto alla cieca). La funzione più lunga dovrebbe comunque funzionare bene. preg_replace ('/([?&”)'.$ varname.' = [^ &] + (& | $) / ',' $ 1 ', $ url) dovrebbe funzionare
Justin

1
PHP 5.4 sembra lamentarsi di @unset - non gli piace il simbolo @, stranamente.
Artem Russakovskii

1
non sorprende - l'operatore @ (nascondi errori) è comunque un male - probabilmente c'è un modo migliore per farlo in PHP 5.4 ora, ma non scrivo PHP da quasi 2 anni, quindi sono un po 'fuori pratica.
Justin

strtok rocks, +1
FrancescoMM

33

Che ne dite di:

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

1
Decisamente più carina. Mi chiedo quale sarebbe comunque migliore. +1
MitMaro

Questo mi ha salvato alcune righe e per me questo è breve e bello. Grazie!
Jens Törnell

5
Utilizzare /(\\?|&)the-var=.*?(&|$)/per rimuovere solo una variabile specifica ( the-varqui).

10

Se l'URL da cui stai tentando di rimuovere la stringa di query è l'URL corrente dello script PHP, puoi utilizzare uno dei metodi menzionati in precedenza. Se hai solo una variabile stringa con un URL al suo interno e vuoi rimuovere tutto ciò che supera il carattere "?" tu puoi fare:

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

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

2
Tieni presente che l'URL potrebbe non contenere un file ?. Il codice restituirà quindi una stringa vuota.
Gumbo

Sì, per sostenere ciò che ha detto @Gumbo, cambierei la seconda riga in:$url = ($pos)? substr($url, 0, $pos) : $url;
CenterOrbit

7

Ispirato dal commento di @MitMaro, ho scritto un piccolo benchmark per testare la velocità delle soluzioni di @Gumbo, @Matt Bridges 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; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; esplodere: 0.19; regexp: 0.31; strpos: 0.18;

Risultato: lo strtok di @ justin è il più veloce.

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


tempo di esecuzione regexp: 0.14591598510742 secondi; tempo di esecuzione dell'esplosione: 0,07137393951416 secondi; tempo di esecuzione strpos: 0,080883026123047 secondi; tempo di esecuzione tok: 0,042459011077881 secondi;
Justin

Molto bella! 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!
Jens Törnell

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

7

Un'altra soluzione ... trovo questa funzione più elegante, rimuoverà anche il carattere '?' 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/>';
}

Produrrà:

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

»Esegui questi test su 3v4l


3

Non potresti usare le variabili del server per farlo?

O funzionerebbe ?:

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

Solo un pensiero.


2

È possibile utilizzare le variabili del server per questo, per esempio $_SERVER['REQUEST_URI'], o meglio ancora: $_SERVER['PHP_SELF'].


4
Ciò ovviamente presuppone che l'URL che sta analizzando sia la pagina che sta eseguendo l'analisi.
MitMaro


0

Che ne dici di una funzione per riscrivere la stringa di query scorrendo l'array $ _GET

! Schema approssimativo di una funzione adeguata

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 del genere sarebbe utile tenere a portata di mano per i link di impaginazione, ecc.

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

0

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

Nel mio codice a volte ho bisogno solo di sezioni, quindi separalo in modo da poter ottenere il valore di ciò di cui ho bisogno 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;

0

Secondo me, il modo migliore sarebbe questo:

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

Controlla se c'è un parametro GET 'i' e lo rimuove se c'è.


0

basta usare javascript echo per eliminare l'URL di qualsiasi variabile con un modulo vuoto che si auto-invia:

    <?
    if (isset($_GET['your_var'])){
    //blah blah blah code
    echo "<script type='text/javascript'>unsetter();</script>"; 
    ?> 

Quindi crea questa funzione javascript:

    function unsetter() {
    $('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body');
    $( "#unset" ).submit();
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.