views:

5981

answers:

4

I have a PHP application that will on occasion have to handle URLs where more than one parameter in the URL will have the same name. Is there an easy way to retrieve all the values for a given key? PHP $_GET returns only the last value.

To make this concrete, my application is an OpenURL resolver, and may get URL parameters like this:

ctx_ver=Z39.88-2004
&rft_id=info:oclcnum/1903126
&rft_id=http://www.biodiversitylibrary.org/bibliography/4323
&rft_val_fmt=info:ofi/fmt:kev:mtx:book
&rft.genre=book
&rft.btitle=At last: a Christmas in the West Indies. 
&rft.place=London,
&rft.pub=Macmillan and co.,
&rft.aufirst=Charles
&rft.aulast=Kingsley
&rft.au=Kingsley, Charles,
&rft.pages=1-352
&rft.tpages=352
&rft.date=1871

(Yes, I know it's ugly, welcome to my world). Note that the key "rft_id" appears twice:

  1. rft_id=info:oclcnum/1903126
  2. rft_id=http://www.biodiversitylibrary.org/bibliography/4323

$_GET will return just http://www.biodiversitylibrary.org/bibliography/4323, the earlier value (info:oclcnum/1903126) having been overwritten.

I'd like to get access to both values. Is this possible in PHP? If not, any thoughts on how to handle this problem?

+6  A: 

I think you'd have to parse $_SERVER['QUERY_STRING'] manually.

Something like (untested):

$query = $_SERVER['QUERY_STRING'];
$vars = array()
foreach (explode('&', $query) as $pair) {
    list($key, $value) = explode('=', $pair);
    $vars[] = array(urldecode($key), urldecode($value));
}

This should give you an array $vars:

array(
    array('ctx_ver'     => 'Z39.88-2004'),
    array('rft_id'      => 'info:oclcnum/1903126'),
    array('rft_id'      => 'http://www.biodiversitylibrary.org/bibliography/4323'),
    array('rft_val_fmt' => 'info:ofi/fmt:kev:mtx:book'),
    array('rft.genre'   => 'book'),
    array('rft.btitle'  => 'At last: a Christmas in the West Indies.'),
    array('rft.place'   => 'London'),
    array('rft.pub'     => 'Macmillan and co.'),
    array('rft.aufirst' => 'Charles'),
    array('rft.aulast'  => 'Kingsley'),
    array('rft.au'      => 'Kingsley, Charles'),
    array('rft.pages'   => '1-352'),
    array('rft.tpages'  => '352'),
    array('rft.date'    => '1871')
)


After having seen Tomalak's answer, I like his data format for the resulting array much better, as it makes it possible to access specific keys by their name.

Stefan Gehrig
rdmpage
+1  A: 

AFAIK there is no way to get duplicate values using $_GET as the second value will overwrite the first

To get around it you could access the raw querystring using $_SERVER['QUERY_STRING'] and then parse it yourself.

Neil Aitken
+8  A: 

Won't work for you as it looks like you don't control the querystring, but another valid answer: Instead of parse querystring, you could appeand '[]' to the end of the name, then PHP will make an array of the items.

IE:

someurl.php?name[]=aaa&name[]=bbb

will give you a $_GET looking like:

array(0=>'aaa', 1=>'bbb')
benlumley
Good suggestion, I wouldnt have thought of thatI assumed that the OP didn't have access to change the values
Neil Aitken
Might not be the answer to OP's requirements, but it is for mine. Thanks!
+11  A: 

Something like:

$query  = explode('&', $_SERVER['QUERY_STRING']);
$params = array();

foreach( $query as $param )
{
  list($name, $value) = explode('=', $param);
  $params[urldecode($name)][] = urldecode($value);
}

gives you:

array(
  'ctx_ver'     => array('Z39.88-2004'),
  'rft_id'      => array('info:oclcnum/1903126', 'http://www.biodiversitylibrary.org/bibliography/4323'),
  'rft_val_fmt' => array('info:ofi/fmt:kev:mtx:book'),
  'rft.genre'   => array('book'),
  'rft.btitle'  => array('At last: a Christmas in the West Indies.'),
  'rft.place'   => array('London'),
  'rft.pub'     => array('Macmillan and co.'),
  'rft.aufirst' => array('Charles'),
  'rft.aulast'  => array('Kingsley'),
  'rft.au'      => array('Kingsley, Charles'),
  'rft.pages'   => array('1-352'),
  'rft.tpages'  => array('352'),
  'rft.date'    => array('1871')
)
Tomalak
I think you're missing a [] in $params[$name] = $value; ;-)
Stefan Gehrig
if (!array_key_exists($name, $params)) $params[$name] = array(); Is unnecessary, $params[$name][] = $value will instantiate the array if it doesn't exist.
Sam
Yeah. I've removed the urldecode()'s into the array assignment as well, no need to have them on an extra line.
Tomalak