如果将键作为变量传递,为什么我不能访问其键中带有 hyphen/dash 的 $_POST 变量?

Why cant I access $_POST variable with a hyphen/dash in its key if passing key as variable?

我为我的 class 编写了一个小的静态方法,其中 returns 如果设置了 $_POST 变量,否则 NULL 。 HTML 形式的输入元素的名称带有连字符,例如 'customer-name'.

所以我想我可以像这样访问它们 $var = $_POST['customer-name']。但是用我的方法:

public static function getPost($param) {
    echo $param." = ".$_POST[$param]."<br/>";
    return isset($_POST[$param]) ? $_POST[$param] : NULL;
}

我不能。当向我的方法添加一些 echo 语句时,我注意到一些奇怪的行为。它切断了连字符后的所有内容,所以我得到了错误:

Notice: Undefined index: customer- in .. on line ..

我是这样测试的:

$arr = (array)$object;
$newArr = array();
foreach($arr as $key => $val) {
    $newKey = str_replace(get_class($object), "", $key);
    $newArr[$newKey] = MyObject::getPost(strtolower(get_class($object))."-".$newKey);
}

这是我测试的输出:

...
Notice: Undefined index: customer- in .. on line 116
customer-id =

Notice: Undefined index: customer- in .. on line 116
customer-name =

Notice: Undefined index: customer- in .. on line 116
customer-phonecode =
...

编辑 1 - 我被要求提供 HTML 表格:

<form action="" method="post" class="form-horizontal" role="form">
   <input type="text" name="customer-name" id="customer-name" class="form-control" placeholder="Name" required="required" autocomplete="off" />
   <select id="customer-phonecode" name="customer-phonecode" class="form-control">
      <option value="+123"></option>
   </select>
</form>

编辑 2 - 在 5.2、5.3、5.4、5.5 php 版本的 phptester.net 上进行了测试。出现同样的错误。

编辑 3 - 测试了以下脚本。如果将字符串作为键传递,我将在超级全局 $_POST/数组中获取元素。但是,如果传递一个指向字符串的变量,则无法访问元素

<?php
$test = array('customer-test1' => 1, 'customer-test2' => 2);
function getPost($param) {
    global $test;
    $newParam = (string)$param;
    echo $param." = ".$test[$newParam]."<br/>";
    return isset($test[$newParam]) ? $test[$newParam] : NULL;
}
class Customer {
    private $test1;
    private $test2;     
    function __construct() { }
}
$object = new Customer();
$arr = (array)$object;
$newArr = array();
foreach($arr as $key => $val) {
    $newKey = str_replace(get_class($object), "", $key);
    $newArr[$newKey] = getPost(strtolower(get_class($object))."-".$newKey);
}

这可能是 PHP 错误吗?

这可能是 PHP 的限制 - 当使用 $_POST 等超全局变量时,会发生一些 "magical" 事情。 PHP对表单元素的名称进行多种转换,例如

<input type="text" name="hello[mate]" />

将作为 $_POST['hello']['mate'] 访问,因为表单名称被作为变量处理。因此使用破折号通常不是一个好主意,因为它们不允许出现在变量名中并且可能会干扰此处。我建议只使用 PHP 中允许用于变量的字符,并将破折号替换为下划线。

所以问题是,将对象转换为数组会将空字符添加到数组键。他们不仅仅是class名字+属性名字。这就是 PHP 在转换时管理私有 class 属性的方式。

$object = new Customer();
$arr = (array)$object;
print_r(array_map("addslashes", array_keys($arr)));

输出:

Array ( 
        [0] => [=11=]Customer[=11=]test1 
        [1] => [=11=]Customer[=11=]test2
      )

我不确定为什么 var_dump() 不显示那些空字节。我想可能是我的下一个问题。所以那些空值仍然存在于我的静态方法参数中。但是为什么 PHP 在 dash/hyphen 之后就停止了?

In PHP we can simply write:

$Tmp= 'hehe';

But for the same in C, we would use the following code:

Char Tmp [4];
Tmp [0] = 'h';
Tmp [1] = 'e';
Tmp [2] = 'h';
Tmp [3] = 'e';
Tmp [4] = '[=13=]';

C handles strings as a character array, it needs a way to define the last character of the string. This is done using a null byte. A null byte is donated by [=19=] in C. So when the program runs, it starts reading the string from the first character until the null byte is reached. This creates a problem. As we know, PHP is also implemented in C. This can become an issue, because some functions in PHP might handle an input string as they are handled by C.

来源:#71673, null-byte-injection-php

编辑 1:添加了解决方案

解决方案是在我的 foreach 循环中用 "" 替换 '\0' 字符以及 class 名称:

foreach($arr as $key => $val) {
    $newKey = str_replace(array(get_class($object), "[=14=]"), "", $key);
    $newArr[$newKey] = getPost(strtolower(get_class($object))."-".$newKey);
}