如何从PHP中的URL获取具有相同名称的多个参数

时间:2008-12-09 16:33:13

标签: php url parameters

我有一个PHP应用程序,有时必须处理URL中的多个参数具有相同名称的URL。是否有一种简单的方法来检索给定密钥的所有值? PHP $ _GET仅返回最后一个值。

为了使这个具体,我的应用程序是一个OpenURL解析器,可能会得到这样的URL参数:

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

(是的,我知道这很难看,欢迎来到我的世界)。请注意,键“rft_id”出现两次:

  1. rft_id=info:oclcnum/1903126
  2. rft_id=http://www.biodiversitylibrary.org/bibliography/4323
  3. $_GET只返回http://www.biodiversitylibrary.org/bibliography/4323,之前的值(info:oclcnum/1903126)已被覆盖。

    我想要访问这两个值。这可能在PHP?如果没有,有关如何处理这个问题的任何想法?

7 个答案:

答案 0 :(得分:65)

类似的东西:

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

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

给你:

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')
)

答案 1 :(得分:38)

不会对你起作用,因为它看起来你不控制查询字符串,而是另一个有效的答案:你可以在名称的末尾加上'[]',而不是解析查询字符串,然后PHP会创建一个项目数组。

IE:

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

会给你一个$ _GET看起来像:

array(0=>'aaa', 1=>'bbb')

答案 2 :(得分:10)

我认为您必须手动解析$_SERVER['QUERY_STRING']

像(未经测试)的东西:

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

这会给你一个数组$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')
)

在看到Tomalak's回答后,我更喜欢结果数组的数据格式,因为它可以按名称访问特定的密钥。

答案 3 :(得分:6)

没有必要为此使用愚蠢的explode变通办法。一个简单的正则表达式可以更容易地使用多个类似命名的参数来纠正QUERY_STRING:

// Replace `&x=1&x=2` into `x[]=1&x[]=2`
$qs = preg_replace("/(?<=^|&)(\w+)(?==)/", "$1[]", $_SERVER["QUERY_STRING"]);

然后就像使用parse_str一样简单:

parse_str($qs, $new_GET);

这样可以立即正确解码%xy网址。

如果您只想将一个或几个特定参数提取为数组,则在正则表达式中使用(id|name)而不是(\w+)

答案 4 :(得分:3)

AFAIK无法使用$_GET获取重复值,因为第二个值将覆盖第一个

要解决此问题,您可以使用$_SERVER['QUERY_STRING']访问原始查询字符串,然后自行解析。

答案 5 :(得分:2)

假设你有一个像这样的查询字符串:

  

参数1 = 2549&安培;应用程序的名字= APPNAME1&安培;应用程序的名字= appName2&安培;应用程序的名字= appName3&安培;应用程序的名字= appName4&安培;应用程序的名字= appName5&安培;的AppType = thetype&安培; idsess = 1231324567980147dzeze55sd4&安培;行动= myaction

你可以这样做:

public static function getMultipleParameters()
    {
        $query = $_SERVER['QUERY_STRING'];
        $vars = array();
        $second = array();
        foreach (explode('&', $query) as $pair) {
            list($key, $value) = explode('=', $pair);
            if('' == trim($value)){
                continue;
            }

            if (array_key_exists($key, $vars)) {
                if (!array_key_exists($key, $second))
                    $second[$key][] .= $vars[$key];
                $second[$key][] = $value;
            } else {
                $vars[$key] = urldecode($value);
            }
        }
        return array_merge($vars, $second);
    }

这给出了:

array (
  'param1' => '2549',
  'appname' => 
      array (
        0 => 'appName1',
        1 => 'appName2',
        2 => 'appName3',
        3 => 'appName4',
        4 => 'appName5',
  ),
  'apptype' => 'thetype',
  'idsess' => '1231324567980147dzeze55sd4',
  'action' => 'myaction',
);

希望有所帮助;)

答案 6 :(得分:2)

分享我此版本的功能

function parse_mstr($query_string,&$query=array()){
    $query = $query? $query: array();
    $params  = explode('&', $query_string);
    foreach( $params as $param ){
        $k = $param;
        $v = '';
        if(strpos($param,'=')){
            list($name, $value) = explode('=', $param);
            $k = rawurldecode($name);
            $v = rawurldecode($value);
        }
        if(array_key_exists($k, $query)){
            if(is_array($query[$k])){
                $query[$k][] = $v;
            }else{
                $query[$k] = array($query[$k],$v);
            }
        }else{
            $query[$k] = $v;
        }
    }
}

// usage
parse_mstr('a=1&a=2&b=3', $arr);

// resulting array
$arr = [
    'a' => ['1', '2'],
    'b' => '3'
]