Stripping A Query Parameter From A URL in PHP

Published: March 1, 2017

Tags:

Recently I needed a function to remove a single query parameter from a given URL in PHP. This seems like the type of thing that there should be a canonical answer for, but, if you run a Google search, you’ll see that there are many ways to skin this cat.

After giving the task some thought, I wound up implementing essentially what is described in this Stack Overflow answer. In this post, I share the approach, along with the final code.

Breaking Up The URL

The first thing to do is to break the URL string into distinct pieces. PHP’s parse_url function will do this for you.

function http_strip_query_param($url)
{
    return parse_url($url);
}

$url = 'http://example.com/page?keep=1&delete=0';

var_dump(http_strip_query_param($url)) . PHP_EOL;

When we execute this…

$ php http_strip_query_param.php
array(4) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(11) "example.com"
  ["path"]=>
  string(5) "/page"
  ["query"]=>
  string(15) "keep=1&delete=0"
}

Now we’re ready to process the URL.

Replacing The Query Param

parse_url will return query as a string not an array. However, we can use parse_str to convert the query string to an array.

function http_strip_query_param($url)
{
    $pieces = parse_url($url);
    $query = [];
    if ($pieces['query']) {
        parse_str($pieces['query'], $query);
    }

    return $query;
}

$url = 'http://example.com/page?keep=1&delete=0';

var_dump(http_strip_query_param($url)) . PHP_EOL;

Here’s how this will execute…

$ php http_strip_query_param.php
array(2) {
  ["keep"]=>
  string(1) "1"
  ["delete"]=>
  string(1) "0"
}

Note that rather than returning an array, parse_str stores the parsed query string in the variable that it receives as a second argument (or as global variables if a second argument is not supplied).

Once we have the query string as an array we can simply unset the query param we want to strip.

Code

function http_strip_query_param($url, $param)
{
    $pieces = parse_url($url);
    $query = [];
    if ($pieces['query']) {
        parse_str($pieces['query'], $query);
        unset($query[$param]);
    }

    return $query;
}

$url = 'http://example.com/page?keep=1&delete=0';
$param = 'delete';

var_dump(http_strip_query_param($url, $param)) . PHP_EOL;

Result:

$ php http_strip_query_param.php
array(1) {
  ["keep"]=>
  string(1) "1"
}

Then we need to convert $query back to a string and replace $parts['query'] with the our processed query string. We can use http_build_query to convert the array back to a string.

Code

function http_strip_query_param($url, $param)
{
    $pieces = parse_url($url);
    $query = [];
    if ($pieces['query']) {
        parse_str($pieces['query'], $query);
        unset($query[$param]);
        $pieces['query'] = http_build_query($query);
    }

    return $pieces;
}

$url = 'http://example.com/page?keep=1&delete=0';
$param = 'delete';

var_dump(http_strip_query_param($url, $param)) . PHP_EOL;

Result

$ php http_strip_query_param.php
array(4) {
  ["scheme"]=>
  string(4) "http"
  ["host"]=>
  string(11) "example.com"
  ["path"]=>
  string(5) "/page"
  ["query"]=>
  string(6) "keep=1"
}

Re-Assembling The URL

For some reason native PHP does not provide a built in function for re-assembling a URL that has been dis-assembled via parse_url. This seems odd to me considering it provides you with a means to dis-assemble a URL natively.

There are a few options…

  1. Install pecl_http and use the http_build_url function. This function will re-assemble the URL.
  2. Polyfill http_build_url. The code to do so can be found here

Once http_build_url is available (either view the extension or a polyfill) you simply use it to reassemble the pieces.

Code

function http_strip_query_param($url, $param)
{
    $pieces = parse_url($url);
    $query = [];
    if ($pieces['query']) {
        parse_str($pieces['query'], $query);
        unset($query[$param]);
        $pieces['query'] = http_build_query($query);
    }

    return http_build_url($pieces);
}

$url = 'http://example.com/page?keep=1&delete=0';
$param = 'delete';

var_dump(http_strip_query_param($url, $param)) . PHP_EOL;

Result

$ php http_strip_query_param.php
string(30) "http://example.com/page?keep=1"

Clean Up

One of the most common issues I see during code review is indentation that can be prevented by using guard clauses properly. Let’s do a little clean up.

function http_strip_query_param($url, $param)
{
    $pieces = parse_url($url);
    if (!$pieces['query']) {
        return $url;
    }

    $query = [];
    parse_str($pieces['query'], $query);
    if (!isset($query[$param])) {
        return $url;
    }

    unset($query[$param]);
    $pieces['query'] = http_build_query($query);

    return http_build_url($pieces);
}

$url = 'http://example.com/page?keep=1&delete=0';
$param = 'delete';

var_dump(http_strip_query_param($url, $param)) . PHP_EOL;

Result

$ php http_strip_query_param.php
string(30) "http://example.com/page?keep=1"

Conclusion

I hope this post came in useful for some people. If you have any questions or comments, feel free to drop a note below, or, as always, you can reach me on Twitter as well.


Max Chadwick Hi, I'm Max!

I'm a software developer who mainly works in PHP, but loves dabbling in other languages like Go and Ruby. Technical topics that interest me are monitoring, security and performance. I'm also a stickler for good documentation and clear technical writing.

During the day I lead a team of developers and solve challenging technical problems at Rightpoint where I mainly work with the Magento platform. I've also spoken at a number of events.

In my spare time I blog about tech, work on open source and participate in bug bounty programs.

If you'd like to get in contact, you can find me on Twitter and LinkedIn.