PHP截断方括号后的参数名称?

时间:2014-06-06 13:57:21

标签: php url square-bracket

如果URL的参数名称包含方括号(无论它们是否为url编码),PHP将忽略任何后续字符,并且脚本无法使用该字符(例如,通过$ _GET)。

示例请求:

...showget.php?xxx%5B1%5Dyyy=42

$ _ GET:

Array
(
    [xxx] => Array
        (
            [1] => 42
        )
)  

正如你所看到的," yyy"没有成功。 ^^

(在PHP 5.3.28& 5.5.10中测试)

  1. 有人知道这些网址在语法上是否有效吗?
  2. 这种行为是否有意和记录(找不到任何内容),还是应该被视为PHP中的错误?
  3. 如果打算:我可以通过更改特殊设置来更改相应的行为吗?
  4. 谢谢!

3 个答案:

答案 0 :(得分:2)

这是预期的行为。正如您在示例中看到的那样,如果可以的话,PHP就会从GET参数构建数组,也就是说,如果它在变量名中找到方括号。有一个FAQ entry显示了它有时可能有用。

在您的情况下,PHP将xxx[1]yyy=42视为xxx[1]=42,它将成为一个数组。

据我所知,PHP的查询字符串解析无法更改,但您可以使用$_SERVER['QUERY_STRING']并自行解析。

答案 1 :(得分:2)

查询键名中的

[]是PHP的一个提示,例如你想要一个数组。

example.com?foo[]=bar&foo[]=baz

产生

$_GET = array(
   'foo' => array('bar', 'baz')
);

此表示法还允许您在网址中指定密钥:

example.com?foo[bar]=baz

$_GET = array(
   'foo' => array('bar' => 'baz')
);

但是一旦你进入这个数组表示法,你就不允许在[]部分之后的键名中包含任何内容:

example.com?foo[bar]baz=qux

$_GET = array(
   'foo' => array('bar' => 'qux')
);

基本上它与PHP语法有关,其中有些像

$foo['bar']baz

将是语法错误。

答案 2 :(得分:0)

我之前也遇到过这个问题,并编写了一个函数来处理来自POST数据的函数,但不应该花费太多时间来使用GET数据。如此大量的代码只是为了解释PHP不考虑嵌套方括号的事实; - )

/**
 * Gets the _POST data with correct handling of nested brackets:
 * "path[to][data[nested]]=value"
 * "path"
 *    -> "to"
 *       -> "data[nested]" = value
 * @return array
 */
function get_real_post() {

    function set_nested_value(&$arr, &$keys, &$value) {
        $key = array_shift($keys);
        if (count($keys)) {
            // Got deeper to go
            if (!array_key_exists($key, $arr)) {
                // Make sure we can get deeper if we've not hit this key before
                $arr[$key] = array();
            } elseif (!is_array($arr[$key])) {
                // This should never be relevant for well formed input data
                throw new Exception("Setting a value and an array with the same key: $key");
            }
            set_nested_value($arr[$key], $keys, $value);
        } elseif (empty($key)) {
            // Setting an Array
            $arr[] = $value;
        } else {
            // Setting an Object
            $arr[$key] = $value;
        }
    }

    $input = array();
    $parts = array();
    $pairs = explode("&", file_get_contents("php://input"));
    foreach ($pairs as $pair) {
        $key_value = explode("=", $pair, 2);
        preg_match_all("/([a-zA-Z0-9]*)(?:\[([^\[\]]*(?:(?R)[^\[\]]*)*)\])?/", urldecode($key_value[0]), $parts);
        $keys = array($parts[1][0]);
        if (!empty($parts[2][0])) {
            array_pop($parts[2]); // Remove the blank one on the end
            $keys = array_merge($keys, $parts[2]);
        }
        $value = urldecode($key_value[1]);
        if ($value == "true") {
            $value = true;
        } else if ($value == "false") {
            $value = false;
        } else if (is_numeric($value)) {
            if (strpos($value, ".") !== false) {
                $num = floatval($value);
            } else {
                $num = intval($value);
            }
            if (strval($num) === $value) {
                $value = $num;
            }
        }
        set_nested_value($input, $keys, $value);
    }
    return $input;
}