2009-08-09 30 views
76

Tôi có một chuỗi có URL đầy đủ bao gồm các biến GET. Cách tốt nhất để loại bỏ biến GET là gì? Có cách nào tốt đẹp để xóa chỉ một trong số họ?Cách hay để xóa các biến GET bằng PHP?

Đây là một mã mà làm việc nhưng không phải là rất đẹp (tôi nghĩ):

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

Đoạn mã trên chỉ loại bỏ tất cả các biến GET. URL trong trường hợp của tôi được tạo từ CMS nên tôi không cần bất kỳ thông tin nào về biến máy chủ.

+1

Tôi sẽ gắn bó với những gì bạn có trừ khi hiệu suất không phải là vấn đề. Các giải pháp regex được cung cấp bởi Gumbo sẽ được như là đẹp như nó được. – MitMaro

+0

Nó không cần phải đẹp nếu nó đang chạy trong functions.php hoặc bất cứ nơi nào bạn ẩn bit xấu xí của bạn, bạn sẽ chỉ cần xem qs_build() để gọi nó là –

+0

Đây là một cách để làm điều này thông qua một chức năng ẩn danh tốt đẹp. http://stackoverflow.com/questions/4937478/strip-off-url-parameter-with-php/17287657#17287657 – doublejosh

Trả lời

196

Ok, để loại bỏ tất cả các biến, có lẽ đẹp nhất là

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

Xem về strtok here.

Nhanh nhất (xem bên dưới) và xử lý các url không có dấu '?' đúng.

Để chụp url + chuỗi truy vấn và loại bỏ chỉ một biến (mà không sử dụng một regex thay thế, có thể nhanh hơn trong một số trường hợp), bạn có thể làm điều gì đó như:

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

Một regex thay thế để loại bỏ một đơn var có thể trông giống như:

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

Cô ấy định thời gian của một vài phương pháp khác nhau, đảm bảo thời gian được đặt lại giữa các lần chạy.

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

lãm

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; 

thắng strtok, và đến nay là các mã nhỏ nhất.

+0

Ok, tôi đã đổi ý. cách strtok trông thậm chí còn tốt hơn. Các chức năng khác không hoạt động tốt. Tôi đã thử các chức năng trên các biến nhận được? Cbyear = 2013 & test = value và đã viết echo removeqsvar ($ current_url, 'cbyear'); và có kết quả: amp; test = value –

+0

ah yeah ... regex chưa hoàn thành - nó sẽ cần phải thay thế dấu phân cách theo sau và bỏ lỡ dấu phân cách hàng đầu (viết nó là mù). Chức năng dài hơn vẫn hoạt động tốt. preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $)/',' $ 1 ', $ url) sẽ hoạt động – Justin

+2

+1 cho 'strtok', không ai khác nghĩ của điều đó :) – knittl

2

Bạn có thể sử dụng server variables cho việc này, ví dụ: $_SERVER['REQUEST_URI'] hoặc thậm chí tốt hơn: $_SERVER['PHP_SELF'].

+3

Giả định này tất nhiên là url mà anh đang phân tích cú pháp là trang đang thực hiện phân tích cú pháp. – MitMaro

26

Làm thế nào về:

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

Chắc chắn đẹp hơn. Tôi tự hỏi cái nào sẽ hoạt động tốt hơn. +1 – MitMaro

+0

Điều này đã cứu tôi một vài hàng và đối với tôi điều này ngắn và đẹp. Cảm ơn bạn! –

+0

Vẫn đáng giá cao; giải pháp ngắn nhất. – Scharrels

7

Nếu URL mà bạn đang cố gắng để loại bỏ các chuỗi truy vấn từ là URL hiện tại của kịch bản PHP, bạn có thể sử dụng một trong các phương pháp đã đề cập. Nếu bạn chỉ có một biến chuỗi với một URL trong đó và bạn muốn bỏ qua tất cả mọi thứ qua '?' bạn có thể làm:

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

+1 vì đó là câu trả lời duy nhất khác ở đây trả lời câu hỏi và cung cấp giải pháp thay thế. – MitMaro

+1

Bạn nên xem xét rằng URL có thể không chứa '?'. Mã của bạn sau đó sẽ trả về một chuỗi rỗng. – Gumbo

0

Làm thế nào về một chức năng để viết lại chuỗi truy vấn bằng cách lặp qua mảng $ _GET

! phác thảo sơ bộ một chức năng phù hợp

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

Something như thế này sẽ là tốt để giữ cho tiện dụng cho các liên kết pagination, vv

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

Lấy cảm hứng từ những nhận xét của @MitMaro, tôi đã viết một chuẩn mực nhỏ để kiểm tra tốc độ của các giải pháp của @Gumbo, @ Matt Bridges và @justin đề nghị trong câu hỏi:

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; 

Res ult: @ justin strtok là nhanh nhất.

Lưu ý: thử nghiệm trên hệ thống Debian Lenny cục bộ với Apache2 và PHP5.

+0

thời gian thực hiện regexp: 0.14591598510742 giây; thời gian thực hiện phát nổ: 0,07137393951416 giây; strpos thời gian thực hiện: 0.080883026123047 giây; thời gian thực hiện tok: 0.042459011077881 giây; – Justin

+0

Rất đẹp! Tôi nghĩ tốc độ là quan trọng. Đó không phải là điều duy nhất sẽ xảy ra. Một ứng dụng web có thể có hàng trăm chức năng. "Đó là tất cả trong các chi tiết". Cảm ơn, bỏ phiếu! –

+0

Justin, cảm ơn.Kịch bản bây giờ đã được dọn sạch và đưa giải pháp của bạn vào tài khoản. – Scharrels

0
@list($url) = explode("?", $url, 2); 
2

Bạn không thể sử dụng biến máy chủ để thực hiện việc này?

Hoặc sẽ làm việc này ?:

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

Chỉ cần một ý nghĩ.

0

basename($_SERVER['REQUEST_URI']) trả về tất cả mọi thứ sau và bao gồm cả '?',

Trong mã của tôi đôi khi tôi chỉ cần phần, vì vậy tách nó ra để tôi có thể nhận được giá trị của những gì tôi cần một cách nhanh chóng. Không chắc chắn về tốc độ hiệu suất so với các phương pháp khác, nhưng nó thực sự hữu ích cho tôi.

$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; 
5

Một giải pháp khác ... Tôi thấy chức năng này thanh lịch hơn, nó cũng sẽ xóa dấu '?' nếu khóa cần xóa là khóa duy nhất trong chuỗi truy vấn.

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

Các xét nghiệm:

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

Will đầu ra:

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 

» Run these tests on 3v4l

0

Theo tôi, cách tốt nhất sẽ là:

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

Nó sẽ kiểm tra nếu có tham số 'i' GET và xóa nó nếu có.

Các vấn đề liên quan