Reputation: 24778
I have a string with a full URL including GET variables. Which is the best way to remove the GET variables? Is there a nice way to remove just one of them?
This is a code that works but is not very beautiful (I think):
$current_url = explode('?', $current_url);
echo $current_url[0];
The code above just removes all the GET variables. The URL is in my case generated from a CMS so I don't need any information about server variables.
Upvotes: 106
Views: 186368
Reputation: 7606
Another solution... I find this function more elegant, it will also remove the trailing '?' if the key to remove is the only one in the query string.
/**
* 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;
}
Tests:
$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 output:
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
Upvotes: 9
Reputation: 15
just use echo'd javascript to rid the URL of any variables with a self-submitting, blank form:
<?
if (isset($_GET['your_var'])){
//blah blah blah code
echo "<script type='text/javascript'>unsetter();</script>";
?>
Then make this javascript function:
function unsetter() {
$('<form id = "unset" name = "unset" METHOD="GET"><input type="submit"></form>').appendTo('body');
$( "#unset" ).submit();
}
Upvotes: 0
Reputation: 5069
Ok, to remove all variables, maybe the prettiest is
$url = strtok($url, '?');
See about strtok
here.
Its the fastest (see below), and handles urls without a '?' properly.
To take a url+querystring and remove just one variable (without using a regex replace, which may be faster in some cases), you might do something like:
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;
}
A regex replace to remove a single var might look like:
function removeqsvar($url, $varname) {
return preg_replace('/([?&])'.$varname.'=[^&]+(&|$)/','$1',$url);
}
Heres the timings of a few different methods, ensuring timing is reset inbetween runs.
<?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; ";
shows
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 wins, and is by far the smallest code.
Upvotes: 270
Reputation: 97
In my opinion, the best way would be this:
<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?>
It checks if there is an 'i' GET parameter, and removes it if there is.
Upvotes: 0
Reputation: 41
Couldn't you use the server variables to do this?
Or would this work?:
unset($_GET['page']);
$url = $_SERVER['SCRIPT_NAME'] ."?".http_build_query($_GET);
Just a thought.
Upvotes: 4
Reputation: 671
basename($_SERVER['REQUEST_URI'])
returns everything after and including the '?',
In my code sometimes I need only sections, so separate it out so I can get the value of what I need on the fly. Not sure on the performance speed compared to other methods, but it's really useful for me.
$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;
Upvotes: 0
Reputation: 3055
Inspired by the comment of @MitMaro, I wrote a small benchmark to test the speed of solutions of @Gumbo, @Matt Bridges and @justin the proposal in the question:
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;
Result: @justin's strtok is the fastest.
Note: tested on a local Debian Lenny system with Apache2 and PHP5.
Upvotes: 7
Reputation: 49425
If the URL that you are trying to remove the query string from is the current URL of the PHP script, you can use one of the previously mentioned methods. If you just have a string variable with a URL in it and you want to strip off everything past the '?' you can do:
$pos = strpos($url, "?");
$url = substr($url, 0, $pos);
Upvotes: 11
Reputation: 3606
How about a function to rewrite the query string by looping through the $_GET array
! Rough outline of a suitable function
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 like this would be good to keep handy for pagination links etc.
<a href="?p=3&<?= query_string_exclude(array('p')) ?>" title="Click for page 3">Page 3</a>
Upvotes: 0
Reputation: 3055
You can use the server variables for this, for example $_SERVER['REQUEST_URI']
, or even better: $_SERVER['PHP_SELF']
.
Upvotes: 2