PHP ile GET değişkenlerini kaldırmanın güzel yolu?


94

GET değişkenlerini içeren tam URL'ye sahip bir dizem var. GET değişkenlerini kaldırmanın en iyi yolu hangisidir? Bunlardan sadece birini çıkarmanın güzel bir yolu var mı?

Bu çalışan ama çok da güzel olmayan bir kod (sanırım):

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

Yukarıdaki kod yalnızca tüm GET değişkenlerini kaldırır. URL benim durumumda bir CMS'den oluşturuldu, bu nedenle sunucu değişkenleri hakkında herhangi bir bilgiye ihtiyacım yok.


1
Performans bir sorun olmadığı sürece sahip olduklarına sadık kalırım. Gumbo tarafından sağlanan regex çözümü olabildiğince güzel olacak.
MitMaro

Functions.php'ye giriyorsa veya çirkin bitlerinizi nerede saklasanız güzel olmasına gerek yok, onu çağırmak için sadece qs_build () 'i görmeniz gerekecek
Soru İşareti

İşte bunu güzel bir anonim işlev aracılığıyla yapmanın bir yolu. stackoverflow.com/questions/4937478/…
doublejosh

URL parçasına ne dersiniz? Aşağıda gördüğüm çözümlerin tümü, kodunuzun yaptığı gibi parçayı da atıyor.
Marten Koetsier

Yanıtlar:


236

Tamam, tüm değişkenleri kaldırmak için belki de en güzeli

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

strtokBuraya bakın .

En hızlısıdır (aşağıya bakın) ve URL'leri "?" Olmadan işler. uygun şekilde.

Bir url + sorgu dizesi almak ve yalnızca bir değişkeni kaldırmak için (bazı durumlarda normal ifade değiştirmeyi kullanmadan, ki bu bazı durumlarda daha hızlı olabilir), aşağıdaki gibi bir şey yapabilirsiniz:

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

Tek bir değişkeni kaldırmak için normal ifade değişikliği şöyle görünebilir:

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

İşte birkaç farklı yöntemin zamanlamaları, çalıştırmalar arasında zamanlamanın sıfırlanmasını sağlar.

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

gösterir

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 kazanır ve açık farkla en küçük koddur.


Tamam, fikrimi değiştirdim. strtok yolu daha da iyi görünüyor. Diğer işlevler o kadar iyi çalışmadı. Bu get değişkenleri üzerindeki fonksiyonları denedim? Cbyear = 2013 & test = value ve echo removeqsvar ($ current_url, 'cbyear'); ve sonucu aldı: amp; test = value
Jens Törnell

ah evet ... normal ifade tamamlanmadı - sondaki sınırlayıcıyı değiştirmeli ve baştaki sınırlayıcıyı atlamalıdır (kör olarak yazılmıştır). Daha uzun işlev yine de iyi çalışmalıdır. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $) / ',' $ 1 ', $ url) çalışmalıdır
Justin

1
PHP 5.4 @unset'ten şikayet ediyor gibi görünüyor - garip bir şekilde @ sembolünü sevmiyor.
Artem Russakovskii

1
şaşırtıcı değil - @ operatörü (hataları gizle) zaten kötüdür - muhtemelen şimdi PHP 5.4'te bunu yapmanın daha iyi bir yolu var, ancak neredeyse 2 yıldır PHP yazmadığım için uygulama.
Justin

strtok kayalar, +1
FrancescoMM

33

Peki ya:

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

1
Kesinlikle daha güzel. Hangisinin daha iyi performans göstereceğini merak ediyorum. +1
MitMaro

Bu bana birkaç sıra kazandırdı ve benim için bu kısa ve güzel. Teşekkür ederim!
Jens Törnell

5
/(\\?|&)the-var=.*?(&|$)/Yalnızca belirli bir değişkeni kaldırmak için kullanın ( the-varburada).

10

Sorgu dizesini kaldırmaya çalıştığınız URL, PHP komut dosyasının geçerli URL'siyse, daha önce bahsedilen yöntemlerden birini kullanabilirsiniz. Yalnızca içinde URL olan bir dize değişkeniniz varsa ve '?' İşaretini geçen her şeyi çıkarmak istiyorsanız yapabilirsin:

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

+1 çünkü burada soruyu yanıtlayan ve bir alternatif sunan diğer tek yanıt budur.
MitMaro

2
URL'nin bir ?. Kodunuz daha sonra boş bir dize döndürecektir.
Gumbo

Evet @Gumbo'nun söylediği şeyi geri almak için, ikinci satırı şu şekilde değiştirirdim:$url = ($pos)? substr($url, 0, $pos) : $url;
CenterOrbit

7

@MitMaro'nun yorumundan esinlenerek, @Gumbo, @Matt Bridges ve @justin'in çözümlerinin hızını test etmek için küçük bir ölçüt yazdım sorudaki öneriye:

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; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; patlatma: 0.19; regexp: 0.31; strpos: 0.18;

Sonuç: @ justin's strtok en hızlısıdır.

Not: Apache2 ve PHP5 ile yerel Debian Lenny sisteminde test edilmiştir.


regexp yürütme süresi: 0.14591598510742 saniye; yürütme süresini patlatma: 0,07137393951416 saniye; strpos yürütme süresi: 0.080883026123047 saniye; tok yürütme süresi: 0,042459011077881 saniye;
Justin

Çok hoş! Bence hız önemli. Olacak tek şey bu değil. Bir web uygulamasının yüzlerce işlevi olabilir. "Her şey ayrıntıda gizli". Teşekkürler, oy verin!
Jens Törnell

Justin, teşekkürler. Komut dosyası şimdi temizlenir ve çözümünüzü dikkate alır.
Scharrels

7

Başka bir çözüm ... Bu işlevi daha zarif buluyorum, sondaki '?' Kaldırılacak anahtar sorgu dizesindeki tek anahtar ise.

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

Testler:

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

Çıktı:

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

»Bu testleri 3v4l'de çalıştırın


3

Bunu yapmak için sunucu değişkenlerini kullanamaz mısınız?

Yoksa bu işe yarar mı?

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

Sadece bir düşünce.


2

Sen kullanabilirsiniz sunucu değişkenlerini örneğin bunun için $_SERVER['REQUEST_URI']daha iyi ya: $_SERVER['PHP_SELF'].


4
Bu, elbette ayrıştırdığı url'nin ayrıştırmayı yapan sayfa olduğunu varsayar.
MitMaro


0

$ _GET dizisi üzerinden döngü yaparak sorgu dizesini yeniden yazan bir işleve ne dersiniz?

! Uygun bir işlevin kaba taslağı

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

Bunun gibi bir şey, sayfalandırma bağlantıları vb. İçin kullanışlı olabilir.

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

0

basename($_SERVER['REQUEST_URI']) "?" dahil olmak üzere sonrasındaki her şeyi döndürür,

Kodumda bazen sadece bölümlere ihtiyacım var, bu yüzden onları ayırın, böylece ihtiyaç duyduğum şeyin değerini anında elde edebilirim. Diğer yöntemlere kıyasla performans hızından emin değilim, ancak benim için gerçekten yararlı.

$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

Bence en iyi yol şudur:

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

Bir 'i' GET parametresi olup olmadığını kontrol eder ve varsa onu kaldırır.


0

kendi kendine gönderilen boş bir formla herhangi bir değişkenin URL'sini silmek için yalnızca yankılı javascript kullanın:

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

Ardından bu javascript işlevini yapın:

    function unsetter() {
    $('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body');
    $( "#unset" ).submit();
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.