Cara yang bagus untuk menghapus variabel GET dengan PHP?

94

Saya memiliki string dengan URL lengkap termasuk variabel GET. Manakah cara terbaik untuk menghapus variabel GET? Adakah cara yang bagus untuk menghapus salah satunya?

Ini adalah kode yang berfungsi tetapi tidak terlalu bagus (menurut saya):

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

Kode di atas hanya menghapus semua variabel GET. Dalam kasus saya, URL dibuat dari CMS jadi saya tidak memerlukan informasi apa pun tentang variabel server.

Jens Törnell
sumber
1
Saya akan tetap berpegang pada apa yang Anda miliki kecuali kinerja tidak menjadi masalah. Solusi regex yang dipasok oleh Gumbo akan menjadi secantik yang didapat.
MitMaro
Tidak perlu cantik jika menggunakan functions.php atau di mana pun Anda menyembunyikan bit jelek Anda, Anda hanya perlu melihat qs_build () untuk memanggilnya
Tanda Tanya
Berikut adalah cara untuk melakukan ini melalui fungsi anonim yang bagus. stackoverflow.com/questions/4937478/…
doublejosh
Bagaimana dengan fragmen url? Solusi yang saya lihat di bawah semua membuang fragmen juga, sama seperti kode Anda.
Marten Koetsier

Jawaban:

236

Oke, untuk menghapus semua variabel, mungkin yang tercantik adalah

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

Lihat tentang di strtoksini .

Ini yang tercepat (lihat di bawah), dan menangani url tanpa '?' tepat.

Untuk mengambil url + querystring dan menghapus hanya satu variabel (tanpa menggunakan regex replace, yang mungkin lebih cepat dalam beberapa kasus), Anda dapat melakukan sesuatu seperti:

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

Penggantian regex untuk menghapus satu var mungkin terlihat seperti:

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

Berikut adalah pengaturan waktu dari beberapa metode yang berbeda, memastikan pengaturan waktu diatur ulang di antara proses.

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

acara

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 menang, dan sejauh ini merupakan kode terkecil.

Justin
sumber
Oke, saya berubah pikiran. cara strtok terlihat lebih baik. Fungsi lainnya tidak bekerja dengan baik. Saya mencoba fungsi pada variabel get ini? Cbyear = 2013 & test = value dan menulis echo removeqsvar ($ current_url, 'cbyear'); dan mendapatkan hasil: amp; test = value
Jens Törnell
ah ya ... regex tidak lengkap - itu harus mengganti pembatas trailing dan melewatkan yang terdepan (menulis itu buta). Fungsi yang lebih lama masih harus berfungsi dengan baik. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $) / ',' $ 1 ', $ url) seharusnya berfungsi
Justin
1
PHP 5.4 tampaknya mengeluh tentang @unset - anehnya ia tidak menyukai simbol @.
Artem Russakovskii
1
tidak mengherankan - operator @ (sembunyikan kesalahan) agak jahat - mungkin ada cara yang lebih baik untuk melakukannya di PHP 5.4 sekarang, tetapi saya belum pernah menulis PHP selama hampir 2 tahun sekarang jadi saya agak ketinggalan praktek.
Justin
strtok rocks, +1
FrancescoMM
33

Bagaimana tentang:

preg_replace('/\\?.*/', '', $str)
Gumbo
sumber
1
Jelas lebih cantik. Saya ingin tahu mana yang akan berkinerja lebih baik. +1
MitMaro
Ini menyelamatkan saya beberapa baris dan bagi saya ini pendek dan indah. Terima kasih!
Jens Törnell
5
Gunakan /(\\?|&)the-var=.*?(&|$)/untuk menghapus hanya variabel tertentu (di the-varsini).
10

Jika URL tempat Anda mencoba menghapus string kueri adalah URL skrip PHP saat ini, Anda dapat menggunakan salah satu metode yang disebutkan sebelumnya. Jika Anda hanya memiliki variabel string dengan URL di dalamnya dan Anda ingin menghapus semuanya setelah '?' Anda dapat melakukan:

$pos = strpos($url, "?");
$url = substr($url, 0, $pos);
Matt Bridges
sumber
+1 karena ini satu-satunya jawaban lain di sini yang menjawab pertanyaan dan memberikan alternatif.
MitMaro
2
Anda harus mempertimbangkan bahwa URL mungkin tidak berisi ?. Kode Anda kemudian akan mengembalikan string kosong.
Gumbo
Ya untuk mendukung apa yang dikatakan @Gumbo, saya akan mengubah baris kedua menjadi:$url = ($pos)? substr($url, 0, $pos) : $url;
CenterOrbit
7

Terinspirasi oleh komentar @MitMaro, saya menulis patokan kecil untuk menguji kecepatan solusi @Gumbo, @Matt Bridges dan @justin proposal dalam pertanyaan:

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; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;
strtok: 0,12; meledak: 0,19; regexp: 0,31; strpos: 0,18;

Hasilnya: strtok @ justin's paling cepat.

Catatan: diuji pada sistem Debian Lenny lokal dengan Apache2 dan PHP5.

Scharrels
sumber
waktu eksekusi regexp: 0,14591598510742 detik; waktu eksekusi meledak: 0,07137393951416 detik; waktu eksekusi strpos: 0,080883026123047 detik; waktu eksekusi tok: 0,042459011077881 detik;
Justin
Sangat bagus! Saya pikir kecepatan itu penting. Itu bukan satu-satunya hal yang akan terjadi. Aplikasi web dapat memiliki ratusan fungsi. "Semuanya ada di detailnya". Terima kasih, pilih!
Jens Törnell
Justin, terima kasih. Skrip sekarang sudah dibersihkan dan mempertimbangkan solusi Anda.
Scharrels
7

Solusi lain ... Menurut saya fungsi ini lebih elegan, ini juga akan menghilangkan tanda '?' jika kunci yang akan dihapus adalah satu-satunya di string kueri.

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

Tes:

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

Akan menghasilkan:

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

»Jalankan pengujian ini pada 3v4l

Gulungan
sumber
3

Tidak bisakah Anda menggunakan variabel server untuk melakukan ini?

Atau apakah ini akan berhasil ?:

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

Hanya pemikiran saja.

bobert
sumber
2

Anda dapat menggunakan variabel server untuk ini, misalnya $_SERVER['REQUEST_URI'], atau bahkan lebih baik: $_SERVER['PHP_SELF'].

Scharrels
sumber
4
Ini tentu saja mengasumsikan bahwa url yang dia parsing adalah halaman yang melakukan parsing.
MitMaro
2
@list($url) = explode("?", $url, 2);
Rob Haswell
sumber
0

Bagaimana dengan sebuah fungsi untuk menulis ulang string kueri dengan mengulang melalui array $ _GET

! Garis besar kasar dari fungsi yang sesuai

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

Sesuatu seperti ini sebaiknya tetap berguna untuk tautan pagination, dll.

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

basename($_SERVER['REQUEST_URI']) mengembalikan semuanya setelah dan termasuk '?',

Dalam kode saya kadang-kadang saya hanya membutuhkan bagian, jadi pisahkan sehingga saya bisa mendapatkan nilai dari apa yang saya butuhkan dengan cepat. Tidak yakin dengan kecepatan kinerja dibandingkan dengan metode lain, tetapi ini sangat berguna bagi saya.

$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;
Sidupac
sumber
0

Menurut saya, cara terbaik adalah ini:

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

Ia memeriksa apakah ada parameter 'i' GET, dan menghapusnya jika ada.

Joshua Anderson
sumber
0

cukup gunakan javascript bergema untuk menghapus URL variabel apa pun dengan formulir kosong yang dikirim sendiri:

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

Kemudian buat fungsi javascript ini:

    function unsetter() {
    $('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body');
    $( "#unset" ).submit();
    }
Rencana B
sumber