5

One of my sites has some very complicated sorting functions, on top of a pagination, and the various variables add up to a pretty complex URL, which is a huge pain to manage. Is there a way to manage the QUERY_STRING efficiently?

By this I mean... if the url is index.php?catid=3&sort=date&year=2009&page=2 and I wish to have the user jump to page 3, or change the sort method..... how would I preserve the remaining vars without checking for each individual var with an if/else condition and echo them out in the link that would link to page 3 or alternate sort method.

matpie
  • 17,033
  • 9
  • 61
  • 82

7 Answers7

4

To handle actual query strings (string format), you can use parse_str(). When you want to build a query string, use http_build_query().

There's quite a few examples on those documentation pages.

If for some reason you can't use http_build_query, check out my question about the fastest way to implode an associative array.

<?php
$QueryString = 'catid=3&sort=date&year=2009&page=2'; // sample querystring
parse_str($QueryString, $HttpQuery);

print_r($HttpQuery); // will be an associative array

$HttpQuery['page'] = 3; // change any values

$NewQueryString = http_build_query($HttpQuery); // rebuild the querystring
Community
  • 1
  • 1
matpie
  • 17,033
  • 9
  • 61
  • 82
3

PHP supplies you a global $_GET which holds your query string all nicely parsed into elements

$_GET['catid'] will be '3'
$_GET['sort'] will be 'date'
$_GET['year'] will be '2009'

etc

You could unset the ones you don't want to pass along and then move to new url via something like:

$get = array_intersect_key($_GET, array_keys($_GET));
unset($get['sort']);
$url = 'target.php?' . http_build_query($get);
Scott Evernden
  • 39,136
  • 15
  • 78
  • 84
1

If you mean that you would like that the link to page 3 would be only

index.php?page=3

or link to changing the sort method would be only

index.php?sort=date

You would have to store the other variables in session variables (or cookies, if you want them to persist longer).

Something like this:

<?php

  session_start();

  foreach($_GET as $var => $val) {
    // filter any malicious stuff and invalid variables out of $var and $val here
    // like
    if (in_array($var, $array_of_valid_variable_names)) {
      if ($var == 'page') $val = intval($val);

      $_SESSION[$var] = $val;
    }
  }

  // do stuff based on the values stored in $_SESSION

  echo '<a href="index.php?page='.($_SESSION['page'] + 1).'">Next page</a>';
?>
kkyy
  • 12,214
  • 3
  • 32
  • 27
1

Although most of the solutions provided here will work, I think the most simple way to do this will be

// parse query string into an array
$queryData = array();
parse_str($_SERVER['QUERY_STRING'], $queryData);
/*
 * ... manipulate array $queryData
 */
// rebuild query string
$queryString = http_build_query($queryData, null, '&amp;'); // or use & if you don't need XHTML compliance

That's it. Please see documentation on http_build_query() and parse_str() (that's one of those functions whose name was completey messed up - nobody would expect the function to do what it does just by looking at the name).

Stefan Gehrig
  • 82,642
  • 24
  • 155
  • 189
0

I have had the exact same problem with a general "build me a sortable, pageable Table" class. This is why someone invented subprocedures called "functions" in php.

You have to create a function that handles exactly the link-building process. like so:

/**
* $set: associative array of changing vars
* $unset : normal array of vars to delete
**/
function get_link($set,$unset=array())
{
 $set+=$_GET;
 if ($unset && is_array($unset))
   foreach($unset as $idx) 
      unset($set[$idx]);

 if ($set)
   foreach($set as $name=>$value)
      $pairs[]=$name.'='.urlencode($value);

 return $_SERVER['SCRIPT_NAME']."?".join('&',$pairs);
}

UNTESTED CODE! Use your brains

or you could use $_SESSION-vars for pageing and sorting (an' stuff) and have links only change those (which is what i mostly do nowadays)

user32459
  • 31
  • 1
  • 3
0

Add the variable name and value at the end of the query string (changing page to 3):

index.php?catid=3&sort=date&year=2009&page=2&x=page&y=3

Then, after extracting $_GET, use a simple function to check if x and y are set.

If they are, set the variable whose name is contained in x to the value y.

You can use the same link everywhere with a simple addition at the end, and the amount of programming is minimal.

Andy Swift
  • 2,179
  • 3
  • 32
  • 53
  • Interesting solution, but it makes things too complicated and causes duplicate pages to be generated, not good for SEO. – matpie Mar 04 '09 at 07:44
-1

Don't manage the string directly but manage an array ( key => value ) representation of it and only translate it back to string when needed.

One possible way of doing it:

function explodeQueryString( $queryString )
{
    $parts = array();
    if ( strlen( $queryString ) > 1 && substr( $queryString, 0, 1 ) == '?' )
    {
        $q = explode( '&', substr( $queryString, 1 ) );
        foreach( $q as $part )
        {
            list( $key, $value ) = explode( '=', $part );
            $parts[ urldecode( $key ) ] = urldecode( $value );
        }
    }
    return $parts;
}

function implodeQueryString( array $arguments )
{
    $parts = array();
    foreach( $arguments as $key => $value )
    {
        $parts[ ] = sprintf( '%s=%s', urlencode( $key ), urlencode( $value ) );
    }
    return sprintf( '?%s', implode( '&', $parts ) );
}

// $query = $_GET;

$query = '?something=1&somethingelse=2&page=1&yetsomethingelse=3';

$q = explodeQueryString( $query );

print_r( $q );

$q[ 'page' ] += 1;

$query = implodeQueryString( $q );

echo $query;
Kris
  • 40,604
  • 9
  • 72
  • 101
  • i know there is $_GET but that's only for the current request. sometimes you need to parse arbitrary amounts of querystrings. – Kris Mar 04 '09 at 06:52
  • This is exactly what parse_str() and http_build_query() do natively. – matpie Mar 04 '09 at 07:31