Whatever I might have $_REQUESTed, I didn't ask for that

Imagine you have a Drupal site: I have several, so that’s easy for me. Say you’ve got an index aggregating lots of your content in a listing, and it spans lots of pages. It’s probably a view created with the views module, slicing through your content in a special way.

Drupal has a core paging module that sorts out links along the lines of:

[« first] [< previous] [1] [2] [3] … [next >] [last »]

Great. But if, like me, you use the PHP $_REQUEST scope to stick lots of useful internal variables in (e.g. theme configuration, for in case you ever want to move your theme’s javascript/ directory in the future and don’t want it hardwired everywhere) then the pager code goes completely mad. Instead of links like:

http://…&page=2

It adds all the $_REQUEST variables onto the link too, creating:

http://…&page=2&sekrit_variable[]=quux&something_else=bar&blithely_generating_long_links=true

This isn’t a bug; it’s a feature. I’ve checked in theme_pager() and it does this on purpose.

So how to pare back the pager code, so it can still be reused if you want to also get some sort of use out of your $_REQUEST scope? Well, below is a snippet of code which in one sense overrides the default pager theme; but in another sense it just wraps around the core pager code. This is preferable to stubbing out the whole of theme_pager() yourself and then fiddling with it, because you’re introducing fewer maintenance issues by avoiding repetition of 95% the same code.

The principle is for phptemplate_pager() to swap everything briefly out of the $_REQUEST scope, run core theme_pager(), save the returned content somewhere, swap everything back into $_REQUEST and return the core-generated pager HTML as if nothing happened. Presto changeo:

/**
 * Implementation of theme_pager
 *
 * Prevents $_REQUEST[] madness
 * @ingroup themeable
 */
function phptemplate_pager($tags = array(), $limit = 10, $element = 0, $parameters = array()) {
  $temp_request = array();

  // Transfer $_REQUEST variables into array and delete from $_REQUEST
  foreach($_REQUEST as $rk => $rv) {
    $temp_request[$rk] = $rv;
    unset($_REQUEST[$rk]);
  }

  // Run theme_pager as before
  $ret = theme_pager($tags, $limit, $element, $parameters);

  // Transfer variables back
  foreach($temp_request as $rk => $rv) {
    $_REQUEST[$rk] = $rv;
  }

  return $ret;
}

Feel free to use. I see that theme_pager() also does the same thing to the $_COOKIE scope. I know, I know. But you’re on your own with that one. Teach a man to fish, and he can fish for cookies.