PHPでGET変数を削除する美しい方法は?


92

GET変数を含む完全なURLの文字列があります。GET変数を削除する最良の方法はどれですか?それらの1つだけを削除する良い方法はありますか?

これは機能するコードですが、あまり美しくありません(私は思う):

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

上記のコードは、すべてのGET変数を削除するだけです。私の場合、URLはCMSから生成されているので、サーバー変数に関する情報は必要ありません。


1
パフォーマンスが問題にならない限り、私はあなたが持っているものを使い続けます。Gumboが提供する正規表現ソリューションは、それが可能な限りきれいになるでしょう。
MitMaro 2009

functions.phpや醜い部分を隠す場合は、美しくする必要はありません。呼び出すにはqs_build()を参照するだけです
疑問符

これは、素敵な無名関数を介してこれを行う方法です。stackoverflow.com/questions/4937478/...
doublejosh

URLフラグメントはどうですか?以下に示す解決策では、コードと同じように、フラグメントもすべて破棄されます。
Marten Koetsier

回答:


232

さて、すべての変数を削除するには、おそらく最も美しいのは

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

参照してくださいstrtokここに

最速(下記参照)で、「?」なしでURLを処理します。正しく。

url + querystringを使用して変数を1つだけ削除するには(正規表現の置換を使用せず、場合によっては高速になる場合があります)、次のようにします。

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

単一の変数を削除する正規表現の置換は次のようになります。

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

いくつかの異なるメソッドのタイミングを示し、実行と実行の間にタイミングが確実にリセットされるようにします。

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

ショー

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が勝ち、圧倒的に最小のコードです。


はい、気が変わりました。strtokの方法はさらに良く見えます。他の機能はうまく機能しませんでした。これらのget変数で関数を試してみましたか?cbyear = 2013&test = valueおよびecho removeqsvar($ current_url、 'cbyear');と書きました。そして結果を得た:amp; test = value
JensTörnell'09

ああ、そうです...正規表現は完全ではありません-末尾の区切り文字を置き換えて、先頭の区切り文字を見落とす必要があります(ブラインドと書きました)。ただし、長い方の関数は正常に機能します。preg_replace( '/([?&])'.$ varname。' = [^&] +(&| $)/ '、' $ 1 '、$ url)は機能するはずです
Justin

1
PHP 5.4は@unsetについて不満を持っているようです-奇妙なことに@記号は好きではありません。
Artem Russakovskii 2014年

1
驚くことではありません-@演算子(エラーを非表示にする)はとにかく邪悪です-おそらく今はPHP 5.4でそれを行うためのより良い方法がありますが、PHPをほぼ2年間書いていないので、練習。
ジャスティン

strtok rocks、+ 1
FrancescoMM

33

どうですか:

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

1
間違いなくきれい。どちらのほうがパフォーマンスが良いのでしょうか。+1
MitMaro 2009

これにより、数行を節約できました。これは短くて美しいです。ありがとうございました!
JensTörnell、2009

5
/(\\?|&)the-var=.*?(&|$)/特定の変数のみを削除するために使用します(the-varここ)。

10

クエリ文字列を削除しようとしているURLがPHPスクリプトの現在のURLである場合は、前述の方法のいずれかを使用できます。URLを含む文字列変数があり、「?」を過ぎてすべてを削除したい場合 できるよ:

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

+1は、質問に答えて別の選択肢を提供する唯一の回答です。
MitMaro 2009

2
URLにが含まれていない可能性があることを考慮する必要があります?。コードは空の文字列を返します。
ガンボ

:うん@Gumboが、私は第2ラインを変更します、言っバックに$url = ($pos)? substr($url, 0, $pos) : $url;
CenterOrbit

7

@MitMaroのコメントに触発されて、質問の提案である@ Gumbo、@ Matt Bridges、@ justinのソリューションの速度をテストするための小さなベンチマークを書きました。

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;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;
strtok:0.12;分解:0.19;正規表現:0.31; strpos:0.18;

結果:@justinのstrtokが最速です。

注:Apache2とPHP5を使用するローカルのDebian Lennyシステムでテストされています。


正規表現の実行時間:0.14591598510742秒。実行時間の爆発:0.07137393951416秒; strpos実行時間:0.080883026123047秒。tokの実行時間:0.042459011077881秒。
ジャスティン

非常に素晴らしい!スピードが大事だと思います。それが起こるのはそれだけではありません。Webアプリケーションは数百の機能を持つことができます。「それはすべて詳細にあります」。ありがとう、投票してください!
JensTörnell09年

ジャスティン、ありがとう。スクリプトがクリーンアップされ、ソリューションが考慮されます。
Scharrels 2009

7

別の解決策...この関数の方がエレガントだと思います。末尾の「?」削除するキーがクエリ文字列内の唯一のキーである場合。

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

テスト:

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

出力されます:

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

»3v4lでこれらのテストを実行する


3

サーバー変数を使用してこれを行うことはできませんか?

それともこれはうまくいきますか?:

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

ちょっとした考え。


2

あなたは使用することができますサーバー変数を例えば、このために$_SERVER['REQUEST_URI']、あるいはさらに良いです:$_SERVER['PHP_SELF']


4
もちろん、これは彼が解析しているURLが解析を行っているページであることを前提としています。
MitMaro 2009


0

$ _GET配列をループしてクエリ文字列を書き換える関数はどうでしょうか

!適切な機能の大まかな概要

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

このようなものは、ページネーションリンクなどに便利に保つのに良いでしょう。

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

0

basename($_SERVER['REQUEST_URI']) 「?」以降のすべてを返します。

私のコードでは、セクションだけが必要な場合があるので、セクションを分離して、必要なものの値をその場で取得できるようにします。他の方法と比較してパフォーマンスの速度はわかりませんが、それは私にとって本当に便利です。

$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

私の意見では、最良の方法はこれです:

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

'i' GETパラメーターがあるかどうかを確認し、ある場合は削除します。


0

echo'd javascriptを使用して、変数のURLを自己送信型の空白の形式で削除します。

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

次に、このJavaScript関数を作成します。

    function unsetter() {
    $('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body');
    $( "#unset" ).submit();
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.