55

I have some links in a Powerpoint presentation, and for some reason, when those links get clicked, it adds a return parameter to the URL. Well, that return parameter is causing my Joomla site's MVC pattern to get bungled.

What's an efficient way to strip off this return parameter using PHP?

Example: http://mydomain.example/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
tpow
  • 7,600
  • 11
  • 59
  • 84
  • possible duplicate of [Beautiful way to remove GET-variables with PHP?](http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php) – PiTheNumber Mar 05 '13 at 12:17

24 Answers24

115

The safest "correct" method would be:

  1. Parse the url into an array with parse_url()
  2. Extract the query portion, decompose that into an array using parse_str()
  3. Delete the query parameters you want by unset() them from the array
  4. Rebuild the original url using http_build_query()

Quick and dirty is to use a string search/replace and/or regex to kill off the value.

Tamlyn
  • 22,122
  • 12
  • 111
  • 127
Marc B
  • 356,200
  • 43
  • 426
  • 500
93

In a different thread Justin suggests that the fastest way is to use strtok()

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

See his full answer with speed tests as well here: https://stackoverflow.com/a/1251650/452515

Community
  • 1
  • 1
Lars Koudal
  • 1,289
  • 12
  • 14
  • 9
    The question was how to remove the specific GET variable `return` and not to remove all GET variables. – mgutt Jan 17 '20 at 08:57
35

This is to complement Marc B's answer with an example, while it may look quite long, it's a safe way to remove a parameter. In this example we remove page_number

<?php
$x = 'http://url.example/search/?location=london&page_number=1';

$parsed = parse_url($x);
$query = $parsed['query'];

parse_str($query, $params);

unset($params['page_number']);
$string = http_build_query($params);
var_dump($string);
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Sergey Telshevsky
  • 12,077
  • 6
  • 55
  • 78
  • Thank you Sergey, and thank you @Marc B, brilliant help. – luke_mclachlan Mar 06 '15 at 14:52
  • 3
    Comment for anyone who finds themselves using this code that this just returns the query string (minus the parameter you've stripped out.) You won't have a full url any more, if that's what you want. – Codemonkey Nov 15 '18 at 18:00
17
function removeParam($url, $param) {
    $url = preg_replace('/(&|\?)'.preg_quote($param).'=[^&]*$/', '', $url);
    $url = preg_replace('/(&|\?)'.preg_quote($param).'=[^&]*&/', '$1', $url);
    return $url;
}
kraftb
  • 625
  • 5
  • 15
  • Agreed, exactly what I was looking for. regex is my weakness, but I knew it was the answer I needed. – ctrlbrk Apr 27 '20 at 22:50
  • If the url has a #hash at the end following the target parameter, this function will strip it off as well. Careful what you copy / paste, this answer has been out there for 8 years on a question with 150k views and no one has noticed. – Maciej Krawczyk Feb 10 '22 at 11:21
  • Hmm, it seems like most of the answers here will strip out the hash. – Maciej Krawczyk Feb 10 '22 at 11:37
14
parse_str($queryString, $vars);
unset($vars['return']);
$queryString = http_build_query($vars);

parse_str parses a query string, http_build_query creates a query string.

NikiC
  • 100,734
  • 37
  • 191
  • 225
12

Procedural Implementation of Marc B's Answer after refining Sergey Telshevsky's Answer.

function strip_param_from_url($url, $param)
{
    $base_url = strtok($url, '?');                   // Get the base URL
    $parsed_url = parse_url($url);                   // Parse it
                               // Add missing {
    if(array_key_exists('query',$parsed_url)) {      // Only execute if there are parameters
        $query = $parsed_url['query'];               // Get the query string
        parse_str($query, $parameters);              // Convert Parameters into array
        unset($parameters[$param]);                  // Delete the one you want
        $new_query = http_build_query($parameters);  // Rebuilt query string
        $url =$base_url.'?'.$new_query;              // Finally URL is ready
    }
    return $url;            
}

// Usage
echo strip_param_from_url( 'http://url.example/search/?location=london&page_number=1', 'location' )
adilbo
  • 910
  • 14
  • 22
Shahbaz A.
  • 4,047
  • 4
  • 34
  • 55
9

You could do a preg_replace like:

$new_url = preg_replace('/&?return=[^&]*/', '', $old_url);
Aaron Hathaway
  • 4,280
  • 2
  • 19
  • 17
  • 4
    Not a good idea if "?return=" is not the last parameter. A query like "urlerror.com/index.php?return=1&test=abc" would get changed to "urlerror.com/index.php&test=abc" – kraftb Nov 18 '13 at 13:54
  • preg_replace('/return=[^&]?&?/i', '', $_SERVER['REQUEST_URI']); – Chris Greenwood May 27 '14 at 16:32
  • This answer is wrong. Analysis: https://stackoverflow.com/a/47527628/318765 – mgutt Nov 28 '17 at 09:33
7

Here is the actual code for what's described above as the "the safest 'correct' method"...

function reduce_query($uri = '') {
    $kill_params = array('gclid');

    $uri_array = parse_url($uri);
    if (isset($uri_array['query'])) {
        // Do the chopping.
        $params = array();
        foreach (explode('&', $uri_array['query']) as $param) {
          $item = explode('=', $param);
          if (!in_array($item[0], $kill_params)) {
            $params[$item[0]] = isset($item[1]) ? $item[1] : '';
          }
        }
        // Sort the parameter array to maximize cache hits.
        ksort($params);
        // Build new URL (no hosts, domains, or fragments involved).
        $new_uri = '';
        if ($uri_array['path']) {
          $new_uri = $uri_array['path'];
        }
        if (count($params) > 0) {
          // Wish there was a more elegant option.
          $new_uri .= '?' . urldecode(http_build_query($params));
        }
        return $new_uri;
    }
    return $uri;
}

$_SERVER['REQUEST_URI'] = reduce_query($_SERVER['REQUEST_URI']);

However, since this will likely exist prior to the bootstrap of your application, you should probably put it into an anonymous function. Like this...

call_user_func(function($uri) {
    $kill_params = array('gclid');

    $uri_array = parse_url($uri);
    if (isset($uri_array['query'])) {
        // Do the chopping.
        $params = array();
        foreach (explode('&', $uri_array['query']) as $param) {
          $item = explode('=', $param);
          if (!in_array($item[0], $kill_params)) {
            $params[$item[0]] = isset($item[1]) ? $item[1] : '';
          }
        }
        // Sort the parameter array to maximize cache hits.
        ksort($params);
        // Build new URL (no hosts, domains, or fragments involved).
        $new_uri = '';
        if ($uri_array['path']) {
          $new_uri = $uri_array['path'];
        }
        if (count($params) > 0) {
          // Wish there was a more elegant option.
          $new_uri .= '?' . urldecode(http_build_query($params));
        }
        // Update server variable.
        $_SERVER['REQUEST_URI'] = $new_uri;

    }
}, $_SERVER['REQUEST_URI']);

NOTE: Updated with urldecode() to avoid double encoding via http_build_query() function. NOTE: Updated with ksort() to allow params with no value without an error.

doublejosh
  • 5,548
  • 4
  • 39
  • 45
  • 1
    Great examples! Note to others: the 'gclid' in the $kill_params array is what will be removed from the query string portion of the uri. Note also that this method of rebuilding the url may not be complete. Also, I have just come across another approach that may work better for splitting and rejoining more modern URIs than using parse_url(); here: http://nadeausoftware.com/articles/2008/05/php_tip_how_parse_and_build_urls – Damian Green Dec 09 '15 at 16:16
5

This one of many ways, not tested, but should work.

$link = 'http://mydomain.example/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0';
$linkParts = explode('&return=', $link);
$link = $linkParts[0];
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Chuck Morris
  • 1,128
  • 1
  • 8
  • 13
  • 2
    This solution is counting for `return` to be at the last position, if that's not the case you will lose all the other params from `return` param as well. – Dr. House Nov 16 '20 at 14:24
4

Wow, there are a lot of examples here. I am providing one that does some error handling. It rebuilds and returns the entire URL with the query-string-param-to-be-removed, removed. It also provides a bonus function that builds the current URL on the fly. Tested, works!

Credit to Mark B for the steps. This is a complete solution to tpow's "strip off this return parameter" original question -- might be handy for beginners, trying to avoid PHP gotchas. :-)

<?php

function currenturl_without_queryparam( $queryparamkey ) {
    $current_url = current_url();
    $parsed_url = parse_url( $current_url );
    if( array_key_exists( 'query', $parsed_url )) {
        $query_portion = $parsed_url['query'];
    } else {
        return $current_url;
    }

    parse_str( $query_portion, $query_array );

    if( array_key_exists( $queryparamkey , $query_array ) ) {
        unset( $query_array[$queryparamkey] );
        $q = ( count( $query_array ) === 0 ) ? '' : '?';
        return $parsed_url['scheme'] . '://' . $parsed_url['host'] . $parsed_url['path'] . $q . http_build_query( $query_array );
    } else {
        return $current_url;
    }
}

function current_url() {
    $current_url = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
    return $current_url;
}

echo currenturl_without_queryparam( 'key' );

?>
Community
  • 1
  • 1
ptmalcolm
  • 646
  • 5
  • 18
4
$var = preg_replace( "/return=[^&]+/", "", $var ); 
$var = preg_replace( "/&{2,}/", "&", $var );

Second line will just replace && to &

SergeS
  • 11,533
  • 3
  • 29
  • 35
  • Did you down vote everyone else? Not pointing fingers, but everyone has a -1 except for you... – Aaron Hathaway Feb 08 '11 at 20:12
  • If you click on the number of votes it will give you a break down of the votes (I think you need a higher reputation to do this). If you didn't do it, that's cool, just thought it was peculiar that everyone has a -1 except for you. – Aaron Hathaway Feb 08 '11 at 20:20
  • Add a 3-rd "preg_replace" to replace "?&" to "?", like: `$var = preg_replace("/\?&/", "?", $var);` – Vadzym Mar 04 '15 at 16:08
3

very simple

$link = "http://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0"
echo substr($link, 0, strpos($link, "return") - 1);
//output : http://example.com/index.php?id=115&Itemid=283
Bruno Ribeiro
  • 1,280
  • 16
  • 21
3

@MarcB mentioned that it is dirty to use regex to remove an url parameter. And yes it is, because it's not as easy as it looks:

$urls = array(
  'example.com/?foo=bar',
  'example.com/?bar=foo&foo=bar',
  'example.com/?foo=bar&bar=foo',
);

echo 'Original' . PHP_EOL;
foreach ($urls as $url) {
  echo $url . PHP_EOL;
}

echo PHP_EOL . '@AaronHathaway' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('#&?foo=[^&]*#', null, $url) . PHP_EOL;
}

echo PHP_EOL . '@SergeS' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace( "/&{2,}/", "&", preg_replace( "/foo=[^&]+/", "", $url)) . PHP_EOL;
}

echo PHP_EOL . '@Justin' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('/([?&])foo=[^&]+(&|$)/', '$1', $url) . PHP_EOL;
}

echo PHP_EOL . '@kraftb' . PHP_EOL;
foreach ($urls as $url) {
  echo preg_replace('/(&|\?)foo=[^&]*&/', '$1', preg_replace('/(&|\?)foo=[^&]*$/', '', $url)) . PHP_EOL;
}

echo PHP_EOL . 'My version' . PHP_EOL;
foreach ($urls as $url) {
  echo str_replace('/&', '/?', preg_replace('#[&?]foo=[^&]*#', null, $url)) . PHP_EOL;
}

returns:

Original
example.com/?foo=bar
example.com/?bar=foo&foo=bar
example.com/?foo=bar&bar=foo

@AaronHathaway
example.com/?
example.com/?bar=foo
example.com/?&bar=foo

@SergeS
example.com/?
example.com/?bar=foo&
example.com/?&bar=foo

@Justin
example.com/?
example.com/?bar=foo&
example.com/?bar=foo

@kraftb
example.com/
example.com/?bar=foo
example.com/?bar=foo

My version
example.com/
example.com/?bar=foo
example.com/?bar=foo

As you can see only @kraftb posted a correct answer using regex and my version is a little bit smaller.

mgutt
  • 5,867
  • 2
  • 50
  • 77
3

Some of the examples posted are so extensive. This is what I use on my projects.

function removeQueryParameter($url, $param){
    list($baseUrl, $urlQuery) = explode('?', $url, 2);
    parse_str($urlQuery, $urlQueryArr);
    unset($urlQueryArr[$param]);

    if(count($urlQueryArr))
        return $baseUrl.'?'.http_build_query($urlQueryArr);
    else
        return $baseUrl;
}
Whip
  • 1,891
  • 22
  • 43
  • It fails when there is no "?" in the URL. I got "Undefined offset: 1" – Luis Rodriguez Aug 24 '22 at 16:10
  • The function is to remove query parameter, in my case I was expecting one - always. If that's not the case for you, you can add a check for that. – Whip Aug 26 '22 at 04:04
2

Remove Get Parameters From Current Page

<?php
$url_dir=$_SERVER['REQUEST_URI']; 

$url_dir_no_get_param= explode("?",$url_dir)[0];

echo $_SERVER['HTTP_HOST'].$url_dir_no_get_param;
ahmed khan
  • 35
  • 4
1

This should do it:

public function removeQueryParam(string $url, string $param): string
{
    $parsedUrl = parse_url($url);

    if (isset($parsedUrl[$param])) {
        $baseUrl = strtok($url, '?');
        parse_str(parse_url($url)['query'], $query);
        unset($query[$param]);
        return sprintf('%s?%s',
            $baseUrl,
            http_build_query($query)
        );
    }

    return $url;
}
Santi Barbat
  • 2,097
  • 2
  • 21
  • 26
1

Simple solution that will work for every url

With this solution $url format or parameter position doesn't matter, as an example I added another parameter and anchor at the end of $url:

https://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0&bonus=test#test2

Here is the simple solution:

$url = 'https://example.com/index.php?id=115&Itemid=283&return=aHR0cDovL2NvbW11bml0&bonus=test#test2';

$url_query_stirng = parse_url($url, PHP_URL_QUERY);
parse_str( $url_query_stirng, $url_parsed_query );
unset($url_parsed_query['return']);
$url = str_replace( $url_query_stirng, http_build_query( $url_parsed_query ), $url );

echo $url;

Final result for $url string is:

https://example.com/index.php?id=115&Itemid=283&bonus=test#test2
Šime
  • 139
  • 6
0
function remove_attribute($url,$attribute)
 {
    $url=explode('?',$url);
    $new_parameters=false;
    if(isset($url[1]))
    {
        $params=explode('&',$url[1]);
        $new_parameters=ra($params,$attribute);
    }
    $construct_parameters=($new_parameters && $new_parameters!='' ) ? ('?'.$new_parameters):'';
    return $new_url=$url[0].$construct_parameters;
 }
 function ra($params,$attr)
    {   $attr=$attr.'=';
        $new_params=array();

        for($i=0;$i<count($params);$i++)
        {   
            $pos=strpos($params[$i],$attr);

            if($pos===false)
            $new_params[]=$params[$i];

        }
        if(count($new_params)>0)
        return implode('&',$new_params);
        else 
        return false; 
     }

//just copy the above code and just call this function like this to get new url without particular parameter

echo remove_attribute($url,'delete_params'); // gives new url without that parameter

prakash
  • 11
  • 4
0

I know this is an old question but if you only want to remove one or few named url parameter you can use this function:

function RemoveGet_Regex($variable, $rewritten_url): string {
    $rewritten_url = preg_replace("/(\?)$/", "", preg_replace("/\?&/", "?", preg_replace("/((?<=\?)|&){$variable}=[\w]*/i", "", $rewritten_url)));
    return $rewritten_url;
}
function RemoveGet($name): void {
    $rewritten_url = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    if(is_array($name)) {
        for($i = 0; $i < count($name); $i++) {
            $rewritten_url = RemoveGet_Regex($name[$i], $rewritten_url);
            $is_set[] = isset($_GET[$name[$i]]);
        }
        $array_filtered = array_filter($is_set);
        if (!empty($array_filtered)) {
            header("Location: ".$rewritten_url);
        }
    }
    else {
        $rewritten_url = RemoveGet_Regex($name, $rewritten_url);
        if(isset($_GET[$name])) {
            header("Location: ".$rewritten_url);
        }
    }
}

In the first function preg_replace("/((?<=\?)|&){$variable}=[\w]*/i", "", $rewritten_url) will remove the get parameter, and the others will tidy it up. The second function will then redirect.

RemoveGet("id"); will remove the id=whatever from the url. The function can also work with arrays. For your example,

Remove(array("id","Item","return"));

m_j_alkarkhi
  • 337
  • 4
  • 14
0

To strip any parameter from the url using PHP script you need to follow this script:

 function getNewArray($array,$k){
        $dataArray = $array;
        unset($array[$k]);
        $dataArray = $array;
        return $dataArray;  
    }
    
function getFullURL(){
        return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    }

 

     $url = getFullURL(); 
      $url_components = parse_url($url);
      
      // Use parse_str() function to parse the
      // string passed via URL
      parse_str($url_components['query'], $params);
      print_r($params); 

    <ul>
    <?php foreach($params as $k=>$v){?>
    <?php 
    
    $newArray = getNewArray($params,$k);
    $parameters  = http_build_query($newArray);
    $newURL = $_SERVER['PHP_SELF']."?".$parameters;
     ?>
    <li><?=$v;?> <a href="<?=$newURL;?>">X</a>
    <?php }?>
    </ul>
Acnosoft
  • 1
  • 2
  • Welcome to Stack Overflow. Code is a lot more helpful when it is accompanied by an explanation. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please [edit] your answer and explain how it answers the specific question being asked. See [answer]. – ChrisGPT was on strike May 22 '22 at 12:24
0

here is functions optimized for speed. But this functions DO NOT remove arrays like a[]=x&a[1]bb=y&a[2]=z by array name.

function removeQueryParam($query, $param)
{
    $quoted_param = preg_quote($param, '/');
    $pattern = "/(^$quoted_param=[^&]*&?)|(&$quoted_param=[^&]*)/";
    return preg_replace($pattern, '', $query);
}

function removeQueryParams($query, array $params)
{
    if ($params)
    {
        $pattern = '/';
        foreach ($params as $param)
        {
            $quoted_param = preg_quote($param, '/');
            $pattern .= "(^$quoted_param=[^&]*&?)|(&$quoted_param=[^&]*)|";
        }
        $pattern[-1] = '/';
        return preg_replace($pattern, '', $query);  
    }
    return $query;
}
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

I needed to do the same thing in PHP to remove the GET element from the URL when the pagination reached page 1, so I created a function in a helper which I call every time in the main controller.

function fixPagination(){
    //check if exist page parameter and page number == 1
    if(isset($_GET['page']) && $_GET['page'] == '1'){
        //parse url
        $parseUrl = parse_url($_SERVER['REQUEST_URI']);
        parse_str($parseUrl['query'], $newParsedUrl);
        //unset the get page element and keep the other get elements, such as brand
        unset($newParsedUrl['page']);
        $newQueryString = http_build_query($newParsedUrl);
        //check if have another get elements
        if(empty($newQueryString)){
            $newFixUrl = base_url().$parseUrl['path'];
        }else{
            $newFixUrl = base_url().$parseUrl['path'].'?'.$newQueryString;
        }
        //redirect to new url with 301 code
        header("HTTP/1.1 301 Moved Permanently");
        header("Location: ".$newFixUrl);
        exit();
    }
}
0

Building on Whip's implementation of the marked solution, I added some extra options:

  1. An option to return the base URL - if set to false it will only return the re-built query string
  2. An option to exclude the full URL, which will use the query string alone by default.
  3. Changed the $param to an array to be able to exclude multiple query string parameters.
function removeQueryParameters($params = array(), $returnBaseURL = false, $url = null)
{
    $url = is_null($url) ? '?' . $_GET : $url;
    list($baseUrl, $urlQuery) = explode('?', $url, 2);
    parse_str($urlQuery, $urlQueryArr);
    foreach ($params as $param) {
        unset($urlQueryArr[$param]);
    }

    if (count($urlQueryArr)) {
        if ($returnBaseURL) {
            return $baseUrl . '?' . http_build_query($urlQueryArr);
        } else {
            return http_build_query($urlQueryArr);
        }
    } else {
        return $baseUrl;
    }
}
Aidan Hakimian
  • 190
  • 1
  • 14
-1
<? if(isset($_GET['i'])){unset($_GET['i']); header('location:/');} ?>

This will remove the 'i' parameter from the URL. Change the 'i's to whatever you need.