วิธีที่สวยงามในการลบตัวแปร GET ด้วย PHP?


94

ฉันมีสตริงที่มี URL แบบเต็มรวมถึงตัวแปร GET วิธีใดเป็นวิธีที่ดีที่สุดในการลบตัวแปร GET มีวิธีที่ดีในการลบเพียงหนึ่งในนั้นหรือไม่?

นี่เป็นรหัสที่ใช้งานได้ แต่ไม่ค่อยสวยงาม (ฉันคิดว่า):

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

โค้ดด้านบนจะลบตัวแปร GET ทั้งหมด URL อยู่ในกรณีของฉันที่สร้างจาก CMS ดังนั้นฉันจึงไม่ต้องการข้อมูลใด ๆ เกี่ยวกับตัวแปรเซิร์ฟเวอร์


1
ฉันจะยึดติดกับสิ่งที่คุณมีเว้นแต่ประสิทธิภาพจะไม่ใช่ปัญหา โซลูชัน regex ที่จัดทำโดย Gumbo จะสวยอย่างที่คิด
MitMaro

ไม่จำเป็นต้องสวยงามถ้าอยู่ใน functions.php หรือไม่ว่าคุณจะซ่อนบิตที่น่าเกลียดของคุณคุณจะต้องดู qs_build () เพื่อเรียกมัน
เครื่องหมายคำถาม

นี่คือวิธีการดำเนินการผ่านฟังก์ชันนิรนามที่ดี stackoverflow.com/questions/4937478/…
doublejosh

แล้วส่วน url ล่ะ? โซลูชันที่ฉันเห็นด้านล่างทั้งหมดทิ้งส่วนเช่นเดียวกับรหัสของคุณ
Marten Koetsier

คำตอบ:


236

โอเคหากต้องการลบตัวแปรทั้งหมดอาจจะดีที่สุด

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

ดูเกี่ยวกับที่นี่strtok

เร็วที่สุด (ดูด้านล่าง) และจัดการ URL โดยไม่มีเครื่องหมาย "?" อย่างถูกต้อง

หากต้องการใช้ url + querystring และลบเพียงตัวแปรเดียว (โดยไม่ใช้ regex แทนที่ซึ่งอาจเร็วกว่าในบางกรณี) คุณอาจทำสิ่งต่อไปนี้

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

regex แทนที่เพื่อลบตัวแปรเดียวอาจมีลักษณะดังนี้:

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
Jens Törnell

ใช่แล้ว ... regex ยังไม่สมบูรณ์ - จำเป็นต้องแทนที่ตัวคั่นท้ายและพลาดตัวนำหน้า (เขียนว่าตาบอด) ฟังก์ชั่นที่ยาวขึ้นควรยังคงทำงานได้ดี preg_replace ('/([?&])'.$ varname.' = [^ &] + (& | $) / ',' $ 1 ', $ url) ควรใช้งานได้
จัสติน

1
PHP 5.4 ดูเหมือนจะบ่นเกี่ยวกับ @unset - มันไม่ชอบสัญลักษณ์ @ แปลก ๆ
Artem Russakovskii

1
ไม่น่าแปลกใจที่ตัวดำเนินการ @ (ซ่อนข้อผิดพลาด) เป็นสิ่งชั่วร้าย - ตอนนี้อาจเป็นวิธีที่ดีกว่าในการทำใน PHP 5.4 แต่ตอนนี้ฉันไม่ได้เขียน PHP มาเกือบ 2 ปีแล้วดังนั้นฉันจึงไม่ได้ การปฏิบัติ.
จัสติ

strtok rocks, +1
FrancescoMM

33

เกี่ยวกับ:

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

1
สวยกว่าแน่นอน ฉันสงสัยว่าอันไหนจะทำงานได้ดีกว่ากัน +1
MitMaro

สิ่งนี้ช่วยฉันได้สองสามแถวและสำหรับฉันนี่สั้นและสวยงาม ขอบคุณ!
Jens Törnell

5
ใช้/(\\?|&)the-var=.*?(&|$)/เพื่อลบเฉพาะตัวแปรเฉพาะ ( the-varที่นี่)

10

หาก URL ที่คุณพยายามลบสตริงการสืบค้นเป็น URL ปัจจุบันของสคริปต์ PHP คุณสามารถใช้วิธีใดวิธีหนึ่งที่กล่าวถึงก่อนหน้านี้ หากคุณมีตัวแปรสตริงที่มี URL อยู่และคุณต้องการตัดทุกอย่างที่ผ่านเครื่องหมาย "?" คุณทำได้:

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

+1 เนื่องจากเป็นคำตอบเดียวที่ตอบคำถามและให้ทางเลือกอื่น
MitMaro

2
คุณควรพิจารณาว่า URL อาจไม่มีไฟล์?. จากนั้นรหัสของคุณจะส่งคืนสตริงว่าง
Gumbo

ใช่เพื่อย้อนกลับสิ่งที่ @Gumbo พูดฉันจะเปลี่ยนบรรทัดที่สองเป็น:$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; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;
strtok: 0.12; ระเบิด: 0.19; regexp: 0.31; strpos: 0.18;

ผลลัพธ์: @ justin strtok เร็วที่สุด

หมายเหตุ: ทดสอบกับระบบ Debian Lenny ในเครื่องด้วย Apache2 และ PHP5


เวลาดำเนินการ regexp: 0.14591598510742 วินาที; เวลาดำเนินการระเบิด: 0.07137393951416 วินาที; เวลาดำเนินการ strpos: 0.080883026123047 วินาที; เวลาดำเนินการ tok: 0.042459011077881 วินาที;
Justin

ดีมาก! ผมคิดว่าความเร็วเป็นสิ่งสำคัญ ไม่ใช่สิ่งเดียวที่กำลังจะเกิดขึ้น เว็บแอปพลิเคชันสามารถมีฟังก์ชันได้หลายร้อยฟังก์ชัน "ทุกอย่างอยู่ในรายละเอียด" ขอบคุณโหวต!
Jens Törnell

จัสตินขอบคุณ ขณะนี้สคริปต์ได้รับการล้างข้อมูลและคำนึงถึงโซลูชันของคุณ
Scharrels

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


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

จากนั้นสร้างฟังก์ชันจาวาสคริปต์นี้:

    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.