2

The variable ' $return10 ' (for example) is a url, and I need to append ' &var2=example ' to the end. Like this:

 header( "Location: $return10&var2=example" );
 header ("Content-Length: 0");
  exit;

The challenge is not knowing if the url contained in ' $return10 ' will already have a query string.

Choice A) If I use ' &var2=example ' , then sometimes the final url will be ' ://example.com&var2=example ' , with no '?' to start the query string.

Choice B) If I use ' ?var2=example ' , then sometimes the final url will contain two "?"'s starting two different query strings??

Is there a third choice? How would you cover both possibilities using "the correct code?" Thank you.

3 Answers 3

7

Create a function that will append your query code if there is one... And add it if there isn't...

function append_query($url, $query) {
  // Fix for relative scheme URL
  $relativeScheme = false;
  if(substr($url, 0, 3) == '://') {
    $relativeScheme = true;
    $url = 'a' . $url;
  }

  $newUrl = http_build_url($url, array('query' => $query), HTTP_URL_JOIN_QUERY);

  if($relativeScheme) {
    return substr($newUrl, 1);
  }

  return $newUrl;
}

header('Location: ' . append_query($return10, 'var2=example'));

This will work regardless of if your query has a fragment or not.

EDIT: Fixed for relative scheme URL.

If your PHP does not have http_build_url() available (ie.: PECL extension not installed), here is a pure PHP version of it which does not require the extension.

define('HTTP_URL_REPLACE', 1);          // Replace every part of the first URL when there's one of the second URL
define('HTTP_URL_JOIN_PATH', 2);        // Join relative paths
define('HTTP_URL_JOIN_QUERY', 4);       // Join query strings
define('HTTP_URL_STRIP_USER', 8);       // Strip any user authentication information
define('HTTP_URL_STRIP_PASS', 16);      // Strip any password authentication information
define('HTTP_URL_STRIP_AUTH', 32);      // Strip any authentication information
define('HTTP_URL_STRIP_PORT', 64);      // Strip explicit port numbers
define('HTTP_URL_STRIP_PATH', 128);     // Strip complete path
define('HTTP_URL_STRIP_QUERY', 256);    // Strip query string
define('HTTP_URL_STRIP_FRAGMENT', 512); // Strip any fragments (#identifier)
define('HTTP_URL_STRIP_ALL', 1024);     // Strip anything but scheme and host

// Build an URL
// The parts of the second URL will be merged into the first according to the flags argument.
//
// @param mixed     (Part(s) of) an URL in form of a string or associative array like parse_url() returns
// @param mixed     Same as the first argument
// @param int       A bitmask of binary or'ed HTTP_URL constants (Optional)HTTP_URL_REPLACE is the default
// @param array     If set, it will be filled with the parts of the composed url like parse_url() would return
function http_build_url($url, $parts = array (), $flags = HTTP_URL_REPLACE, &$new_url = false) {
  $keys = array (
    'user',
    'pass',
    'port',
    'path',
    'query',
    'fragment'
  );

  // HTTP_URL_STRIP_ALL becomes all the HTTP_URL_STRIP_Xs
  if ($flags & HTTP_URL_STRIP_ALL) {
    $flags |= HTTP_URL_STRIP_USER;
    $flags |= HTTP_URL_STRIP_PASS;
    $flags |= HTTP_URL_STRIP_PORT;
    $flags |= HTTP_URL_STRIP_PATH;
    $flags |= HTTP_URL_STRIP_QUERY;
    $flags |= HTTP_URL_STRIP_FRAGMENT;
  }
  // HTTP_URL_STRIP_AUTH becomes HTTP_URL_STRIP_USER and HTTP_URL_STRIP_PASS
  else if ($flags & HTTP_URL_STRIP_AUTH) {
    $flags |= HTTP_URL_STRIP_USER;
    $flags |= HTTP_URL_STRIP_PASS;
  }

  // Parse the original URL
  $parse_url = parse_url($url);

  // Scheme and Host are always replaced
  if (isset($parts['scheme']))
    $parse_url['scheme'] = $parts['scheme'];

  if (isset($parts['host']))
    $parse_url['host'] = $parts['host'];

  // (If applicable) Replace the original URL with it's new parts
  if ($flags & HTTP_URL_REPLACE) {
    foreach ($keys as $key) {
      if (isset($parts[$key]))
        $parse_url[$key] = $parts[$key];
    }
  } else {
    // Join the original URL path with the new path
    if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) {
      if (isset($parse_url['path']))
        $parse_url['path'] = rtrim(str_replace(basename($parse_url['path']), '', $parse_url['path']), '/') . '/' . ltrim($parts['path'], '/');
      else
        $parse_url['path'] = $parts['path'];
    }

    // Join the original query string with the new query string
    if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) {
      if (isset($parse_url['query']))
        $parse_url['query'] .= '&' . $parts['query'];
      else
        $parse_url['query'] = $parts['query'];
    }
  }

  // Strips all the applicable sections of the URL
  // Note: Scheme and Host are never stripped
  foreach ($keys as $key) {
    if ($flags & (int)constant('HTTP_URL_STRIP_' . strtoupper($key)))
      unset($parse_url[$key]);
  }

  $new_url = $parse_url;

  return ((isset($parse_url['scheme'])) ? $parse_url['scheme'] . '://' : '') . ((isset($parse_url['user'])) ? $parse_url['user'] . ((isset($parse_url['pass'])) ? ':' . $parse_url['pass'] : '') . '@' : '')
    . ((isset($parse_url['host'])) ? $parse_url['host'] : '') . ((isset($parse_url['port'])) ? ':' . $parse_url['port'] : '') . ((isset($parse_url['path'])) ? $parse_url['path'] : '')
    . ((isset($parse_url['query'])) ? '?' . $parse_url['query'] : '') . ((isset($parse_url['fragment'])) ? '#' . $parse_url['fragment'] : '');
}
Sign up to request clarification or add additional context in comments.

3 Comments

instead of replacing the query string of same name, it adds one more if already exists with the same name...
Hi Andrew- what's the license on this? I'd like to include it in an open source Drupal module to remove the dependency on the PECL extension.
There is this library available now too: github.com/jakeasmith/http_build_url
1

Take a look at http://php.net/manual/en/function.parse-url.php and http://www.php.net/manual/en/function.http-build-url.php.

Now you can do something like this:

<?php
$return10 = '... some url here ...';
$newUrl = http_build_url(
    $return10,
    array('query' => 'var2=example'),
    HTTP_URL_JOIN_QUERY
);
?>

Comments

0

You can construct the URI seperately:

if(!strpos($uri, "?"))
  $uri .= "&var2=example"
else
  $uri .= "?var2=example"

header("Location: $uri");

5 Comments

$uri+= won't work, it rather looks like a JavaScript syntax. Use $uri.= instead.
of course rhino. Didn't touch php in a long time, += is used in C# as well, and that's where I spent most of my time in the last weeks ;)
... I need to work off-line and will test ASAP, thank you for the fast answer!
-1: This will definitely not work in situations where the URL has a fragment.
@Andrew Moore thanks for the 'heads up', I will be using some anchors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.