[php] PHP로 GET 변수를 제거하는 아름다운 방법?

GET 변수를 포함하는 전체 URL이있는 문자열이 있습니다. GET 변수를 제거하는 가장 좋은 방법은 무엇입니까? 그중 하나만 제거하는 좋은 방법이 있습니까?

이것은 작동하지만 그다지 아름답 지 않은 코드입니다 (제 생각에).

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

위의 코드는 모든 GET 변수를 제거합니다. 제 경우 URL은 CMS에서 생성되므로 서버 변수에 대한 정보가 필요하지 않습니다.



답변

좋아, 모든 변수를 제거하려면 아마도 가장 예쁜 것은

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

strtok여기를 참조 하십시오 .

가장 빠르며 (아래 참조) ‘?’가없는 URL을 처리합니다. 정확히.

url + querystring을 가져 와서 하나의 변수 만 제거하려면 (정규식 바꾸기를 사용하지 않고 경우에 따라 더 빠를 수 있음) 다음과 같이 할 수 있습니다.

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가 이기고 지금까지 가장 작은 코드입니다.


답변

어때 :

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


답변

쿼리 문자열을 제거하려는 URL이 PHP 스크립트의 현재 URL 인 경우 이전에 언급 한 방법 중 하나를 사용할 수 있습니다. URL이 포함 된 문자열 변수가 있고 ‘?’뒤에있는 모든 것을 제거하려는 경우 넌 할 수있어:

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


답변

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

결과 : @justin의 strtok가 가장 빠릅니다.

참고 : Apache2 및 PHP5를 사용하는 로컬 Debian Lenny 시스템에서 테스트되었습니다.


답변

또 다른 해결책 …이 함수가 더 우아하다는 것을 알았습니다. 또한 후행 ‘?’도 제거합니다. 제거 할 키가 쿼리 문자열에서 유일한 경우.

/**
 * 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에서이 테스트 실행


답변

이를 위해 서버 변수를 사용할 수 없습니까?

아니면 작동할까요? :

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

그냥 생각.


답변

이를 위해 서버 변수 를 사용할 수 있습니다 ( 예 $_SERVER['REQUEST_URI']🙂 $_SERVER['PHP_SELF'].