Mam ciąg z pełnym adresem URL zawierającym zmienne GET. Jaki jest najlepszy sposób na usunięcie zmiennych GET? Czy jest dobry sposób na usunięcie tylko jednego z nich?
To jest kod, który działa, ale nie jest zbyt piękny (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.
Odpowiedzi:
Ok, żeby usunąć wszystkie zmienne, może najładniejsza jest
$url = strtok($url, '?');
Zobacz
strtok
tutaj .Jest najszybszy (patrz poniżej) i obsługuje adresy URL bez znaku „?” prawidłowo.
Aby wziąć adres URL + querystring i usunąć tylko jedną zmienną (bez użycia zamiany wyrażenia regularnego, co może być szybsze w niektórych przypadkach), możesz 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; }
Zastąpienie wyrażenia regularnego w celu usunięcia pojedynczej zmiennej może wyglądać następująco:
function removeqsvar($url, $varname) { return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url); }
Oto czasy kilku różnych metod, zapewniające resetowanie czasu między uruchomieniami.
<?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; ";
przedstawia
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 wygrywa i jest zdecydowanie najmniejszym kodem.
źródło
Co powiesz na:
preg_replace('/\\?.*/', '', $str)
źródło
/(\\?|&)the-var=.*?(&|$)/
do usuwania tylko określonej zmiennej (the-var
tutaj).Jeśli adres URL, z którego próbujesz usunąć ciąg zapytania, jest bieżącym adresem URL skryptu PHP, możesz użyć jednej z wcześniej wspomnianych metod. Jeśli masz tylko zmienną łańcuchową z adresem URL i chcesz usunąć wszystko poza znakiem „?” możesz to zrobić:
$pos = strpos($url, "?"); $url = substr($url, 0, $pos);
źródło
?
. Twój kod zwróci wtedy pusty ciąg.$url = ($pos)? substr($url, 0, $pos) : $url;
Zainspirowany komentarzem @MitMaro napisałem mały benchmark do testowania szybkości rozwiązań @Gumbo, @Matt Bridges i @justin propozycja 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 />"; }
Wynik: strtok @ justina jest najszybszy.
Uwaga: przetestowano na lokalnym systemie Debian Lenny z Apache2 i PHP5.
źródło
Inne rozwiązanie ... Uważam, że ta funkcja jest bardziej elegancka, usunie również końcowe „?” jeśli klucz do usunięcia jest jedynym kluczem 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
»Przeprowadź te testy na 3v4l
źródło
Czy nie mógłbyś użyć do tego zmiennych serwera?
A może to zadziała ?:
unset($_GET['page']); $url = $_SERVER['SCRIPT_NAME'] ."?".http_build_query($_GET);
Tylko myśl.
źródło
Można użyć zmiennych serwera za to, na przykład
$_SERVER['REQUEST_URI']
, albo nawet lepiej:$_SERVER['PHP_SELF']
.źródło
@list($url) = explode("?", $url, 2);
źródło
Co powiesz na funkcję, która przepisuje ciąg zapytania przez zapętlenie tablicy $ _GET
! Zgrubny 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 przydałoby się w przypadku linków do paginacji itp.
<a href="?p=3&<?= query_string_exclude(array('p')) ?>" title="Click for page 3">Page 3</a>
źródło
basename($_SERVER['REQUEST_URI'])
zwraca wszystko po znaku „?” i łącznie z nim,W moim kodzie czasami potrzebuję tylko sekcji, więc oddziel go, aby uzyskać wartość tego, czego potrzebuję w locie. Nie jestem pewien szybkości działania w porównaniu z innymi metodami, ale jest to dla mnie naprawdę przydatne.
$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;
źródło
Moim zdaniem najlepszym sposobem byłoby to:
<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?>
Sprawdza, czy istnieje parametr GET „i” i usuwa go, jeśli istnieje.
źródło
po prostu użyj wyrażonego echo javascript, aby usunąć z adresu URL dowolne zmienne za pomocą samoskładającego się, pustego formularza:
<? if (isset($_GET['your_var'])){ //blah blah blah code echo "<script type='text/javascript'>unsetter();</script>"; ?>
Następnie wykonaj tę funkcję javascript:
function unsetter() { $('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body'); $( "#unset" ).submit(); }
źródło