2009-08-09 15 views
76

Mam ciąg z pełnym adresem URL zawierającym zmienne GET. Jaki jest najlepszy sposób na usunięcie zmiennych GET? Czy istnieje dobry sposób na usunięcie tylko jednego z nich?Piękny sposób na usunięcie zmiennych GET z PHP?

Jest to kod, który działa, ale nie jest bardzo piękne (myślę):

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

Powyższy kod po prostu usuwa wszystkie zmienne GET. Adres URL jest w moim przypadku generowany z CMS, więc nie potrzebuję żadnych informacji o zmiennych serwerowych.

+1

Będę trzymać się tego, co masz, chyba że wydajność nie jest problemem. Rozwiązanie regex dostarczane przez Gumbo będzie tak piękne, jak to tylko możliwe. – MitMaro

+0

To nie musi być piękne, jeśli chodzi o functions.php lub gdziekolwiek ukryjesz swoje brzydkie bity, musisz tylko zobaczyć qs_build(), aby go nazwać –

+0

Oto sposób, aby to zrobić za pomocą ładnej anonimowej funkcji. http://stackoverflow.com/questions/4937478/strip-off-url-parameter-with-php/17287657#17287657 – doublejosh

Odpowiedz

196

Ok, aby usunąć wszystkie zmienne, może najładniejsza jest

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

Zobacz o strtok here.

Jest to najszybszy (patrz poniżej) i obsługuje adresy URL bez "?" prawidłowo.

Aby wziąć url + ciągu kwerendy i usunąć tylko jedną zmienną (bez używania regex zastąpić, które mogą być szybciej w niektórych przypadkach), można zrobić coś takiego:

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 zastąpić w celu usunięcia pojedynczy var może wyglądać następująco:

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

Herezje czasy z kilku różnych metod, zapewniając rozrządu jest resetowany pomiędzy nimi biegnie.

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

pokazuje

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; 

wygrywa strtok i jest zdecydowanie najmniejszy kodu.

+0

OK, zmieniłem zdanie. sposób strtok wygląda jeszcze lepiej. Pozostałe funkcje nie działały tak dobrze. Próbowałem funkcji na tych zmiennych get? Cbyear = 2013 & test = value i napisał echo removeqsvar ($ current_url, 'cbyear'); i uzyskał wynik: amp; test = value –

+0

ah tak ... regex nie jest kompletny - będzie musiał zastąpić ogranicznik końcowy i pominąć wiodący (napisany w ciemno). Jednak dłuższa funkcja powinna nadal działać dobrze. preg_replace ('/([?&])'.$ nazwa_zmiennej.' = [^ &] + (& | $)/',' $ 1 ', $ url) powinno działać – Justin

+2

+1 dla 'strtok', nikt inny nie pomyślał tego :) – knittl

2

Można użyć do tego celu server variables, na przykład $_SERVER['REQUEST_URI'] lub jeszcze lepiej: $_SERVER['PHP_SELF'].

+3

Zakłada to oczywiście, że adres URL, który parsuje, jest stroną, która parsuje. – MitMaro

26

Jak o:

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

Zdecydowanie ładniejsza. Zastanawiam się, który z nich byłby lepszy. +1 – MitMaro

+0

To uratowało mi kilka rzędów i dla mnie jest to krótkie i piękne. Dziękuję Ci! –

+0

Nadal warto awansować; najkrótsze rozwiązanie. – Scharrels

7

Jeśli adres URL, który próbujesz usunąć ciąg kwerendy z jest aktualny adres URL skryptu PHP, można skorzystać z jednej z wyżej wymienionych metod. Jeśli masz tylko zmienną łańcuchową z adresem URL i chcesz usunąć wszystko poza "?" można zrobić:

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

+1, ponieważ jest to jedyna inna odpowiedź, która odpowiada na pytanie i stanowi alternatywę. – MitMaro

+1

Należy wziąć pod uwagę, że adres URL może nie zawierać znaku "?". Twój kod zwróci pusty ciąg. – Gumbo

0

Jak o funkcji przepisać ciąg kwerendy przez zapętlenie za pośrednictwem tablicy $ _GET

! Szorstki zarys odpowiedniej funkcji

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

Coś takiego byłoby dobrze mieć pod ręką za linki paginacji itp

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

zainspirowany komentarzem @MitMaro napisałem mały punkt odniesienia do testowania prędkość rozwiązań @Gumbo, @Matt Bridges i @justin wnioskiem w pytaniu:

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's strtok jest najszybszy.

Uwaga: testowany na lokalnym systemie Debian Lenny za pomocą Apache2 i PHP5.

+0

czas realizacji regexp: 0.14591598510742 sekund; czas wykonania polecenia explode: 0,07137393951416 sekund; czas wykonania strpos: 0.080883026123047 sekund; czas wykonania toka: 0,042459011077881 sekund; – Justin

+0

Bardzo ładne! Myślę, że prędkość jest ważna. To nie jedyna rzecz, która się wydarzy. Aplikacja internetowa może mieć setki funkcji. "Wszystko jest w szczegółach". Dzięki, zagłosuj! –

+0

Justin, dzięki.Skrypt został wyczyszczony i bierze pod uwagę twoje rozwiązanie. – Scharrels

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

Nie możesz użyć zmiennych serwera, aby to zrobić?

Albo to będzie działać ?:

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

Tylko myśl.

0

basename($_SERVER['REQUEST_URI']) wszystko wraca po i w tym „?”,

W moim kodu czasami muszę tylko sekcje, więc oddzielić go więc mogę uzyskać wartość co muszę na bieżąco. Nie jestem pewien szybkości działania w porównaniu do innych metod, ale jest to dla mnie bardzo przydatne.

5

Kolejne rozwiązanie ... Uważam, że funkcja ta jest bardziej elegancka, usunie również końcowe "?" jeśli klucz do usunięcia jest jedyny w ciągu zapytania.

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

Testy:

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

wyświetli:

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

Moim zdaniem, najlepszym sposobem byłoby to:

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

Sprawdza, czy istnieje parametr "i" GET, i usuwa go, jeśli jest.

Powiązane problemy