简体   繁体   English

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

[英]How to get multiple parameters with same name from a URL in PHP

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.我有一个 PHP 应用程序,它有时必须处理 URL 中多个参数具有相同名称的 URL。 Is there an easy way to retrieve all the values for a given key?有没有一种简单的方法来检索给定键的所有值? PHP $_GET returns only the last value. PHP $_GET 只返回最后一个值。

To make this concrete, my application is an OpenURL resolver, and may get URL parameters like this:具体来说,我的应用程序是一个 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

(Yes, I know it's ugly, welcome to my world). (是的,我知道这很丑,欢迎来到我的世界)。 Note that the key "rft_id" appears twice:请注意,键“rft_id”出现了两次:

  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. $_GET将仅返回http://www.biodiversitylibrary.org/bibliography/4323 ,较早的值 ( info:oclcnum/1903126 ) 已被覆盖。

I'd like to get access to both values.我想访问这两个值。 Is this possible in PHP?这在 PHP 中可能吗? If not, any thoughts on how to handle this problem?如果没有,关于如何处理这个问题的任何想法?

Something like:就像是:

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

foreach( $query as $param )
{
  // prevent notice on explode() if $param has no '='
  if (strpos($param, '=') === false) $param += '=';

  list($name, $value) = explode('=', $param, 2);
  $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')
)

Since it's always possible that one URL parameter is repeated, it's better to always have arrays, instead of only for those parameters where you anticipate them.因为总是有可能重复一个 URL 参数,所以最好总是有数组,而不是只为那些您期望它们的参数。

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.对您不起作用,因为看起来您不控制查询字符串,但另一个有效答案是:您可以将 '[]' 添加到名称末尾,而不是解析查询字符串,然后 PHP 将创建一个数组项目。

IE: IE:

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

will give you a $_GET looking like:会给你一个 $_GET 看起来像:

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

I think you'd have to parse $_SERVER['QUERY_STRING'] manually.我认为您必须手动解析$_SERVER['QUERY_STRING']

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 :这应该给你一个数组$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.看过Tomalak 的回答后,我更喜欢他的结果数组的数据格式,因为它可以通过名称访问特定键。

There's no need to use explode workarounds for this.没有必要为此使用explode解决方法。 A simple regex can more easily rectify a QUERY_STRING with multiple like-named parameters:一个简单的正则表达式可以更轻松地使用多个类似命名的参数来纠正 QUERY_STRING:

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

Then it's as simple as using parse_str :然后就像使用parse_str一样简单:

parse_str($qs, $new_GET);

Which has the advantage of correctly decoding %xy URL escapes right away.这具有立即正确解码%xy URL 转义的优点。

If you just want a single or a few specific parameters extracted as array, then use (id|name) instead of (\\w+) in the regex.如果您只想将单个或几个特定参数提取为数组,则在正则表达式中使用(id|name)而不是(\\w+)

Assumed you have a query string like this:假设你有一个这样的查询字符串:

param1=2549&appname=appName1&appname=appName2&appname=appName3&appname=appName4&appname=appName5&apptype=thetype&idsess=1231324567980147dzeze55sd4&action=myaction param1=2549&appname=appName1&appname=appName2&appname=appName3&appname=appName4&appname=appName5&apptype=thetype&idsess=1231324567980147dzeze55sd4&action=myaction

You can do this :你可以这样做 :

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);
    }

That gives :这给出了:

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

Hope that helps ;)希望有帮助;)

Sharing my version of this function分享我的这个功能的版本

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

AFAIK there is no way to get duplicate values using $_GET as the second value will overwrite the first AFAIK 无法使用$_GET获取重复值,因为第二个值将覆盖第一个

To get around it you could access the raw querystring using $_SERVER['QUERY_STRING'] and then parse it yourself.要绕过它,您可以使用$_SERVER['QUERY_STRING']访问原始查询字符串,然后自己解析它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM