PHP 文件输入数组命名与其他输入不同
PHP file input array naming is not like other inputs
我正在 PHP 中实现多用途 html 形式 posting 代码,能够 post 对象图结构。
所以我创建了一些命名规则并基于它们,我在服务器端解析索引。
其中一条规则是这样的:
<input name="myModels[children[0]]" type="text" />
当然上面的命名略有缩短,以便更容易切中要点。
当我从
中检索它们时,该命名非常有效
$_POST
但是当我在文件输入中使用它时,它们从未出现在 $_FILE 全局数组中
和
print_r($_FILES);
为空
PHP supports HTML array feature even with files.
那是为什么呢?为什么这种命名方式([] inside [])适用于 POSTED 数据但不适用于文件数据。
请注意,上传文件本身不是问题。
即使使用数组,上传也很有效。即使是带有键索引的数组。
我想弄清楚的是:
<form action="/Test/uploadTest.php" method="post" enctype="multipart/form-data" >
File1 <input name="myModels[postedFiles[0]]" type="file" /></br>
File2 <input name="myModels[postedFiles[1]]" type="file" /></br>
<input type="submit" value="post" />
</form>
并在 uploadTest.php
的服务器上
print_r($_FILES);
为空。
我的PHP版本有点旧,是PHP5.3.6-13。您是否认为它与我的 PHP 版本有关,或者即使在 PHP 的较新版本中也是某种错误?
提前致谢。
解决方案:@tozer83 和@alvaro 提供的答案都非常有帮助。现在事实证明,多部分形式在处理非标量索引和尝试利用文件输入的 html 数组的优势方面有所不同,以便创建用于创建复杂对象图的表达式,就像其他框架中的其他框架一样语言在 PHP 中不起作用。应该忽略 html 数组或使用其他文字(如括号)来解决此问题。
很难决定应该点击哪些复选标记!考虑到@alvoro 已经获得的高排名,我决定选择@tozer83 的答案,因为他先回答并给出了解决方案。但是@alvaro 的回答很详细,也很有帮助。所以我+1他的回答。
我尝试制作相同的表格,但做了一些修改。
<form action="uploadTest.php" method="post" enctype="multipart/form-data" >
File1 <input name="myModels[postedFiles(0)]" type="file" /></br>
File2 <input name="myModels[postedFiles(1)]" type="file" /></br>
<input type="submit" value="post" />
</form>
print_r($_FILES) 尝试上传文件时的结果:
Array ( [myModels] => Array ( [name] => Array ( [postedFiles(0)] => file1.txt [postedFiles(1)] => file2.txt ) [type] => Array ( [postedFiles(0)] => text/plain [postedFiles(1)] => text/plain ) [tmp_name] => Array ( [postedFiles(0)] => /tmp/phpiHJBb1 [postedFiles(1)] => /tmp/phpSFh4J0 ) [error] => Array ( [postedFiles(0)] => 0 [postedFiles(1)] => 0 ) [size] => Array ( [postedFiles(0)] => 4 [postedFiles(1)] => 4 ) ) )
在此处参考 PHP 手册:
https://secure.php.net/manual/en/features.file-upload.post-method.php
查看示例 #3 以上传一组文件。
这似乎不起作用,但是如果文件太大,这将在您的 php.ini 到 upload_max_filesize 甚至 post_max_size.[=13= 中指定]
首先(只是为了清楚地说明)PHP 不允许非标量值作为数组键。实际上,只能使用字符串和整数。因此,没有语言结构可以容纳 myModels[postedFiles[0]]
这样的东西。 documentation about HTML arrays 并没有真正说明当无法解析的字段名称出现时会发生什么。
当我们把它推到极限时会发生什么?显然,行为因我们谈论的超全局而异。在$_POST
中,PHP尽量创建数组:
<input name="good[array][0]" type="text">
<input name="myModels[children[0]]" type="text">
array(2) {
["good"]=>
array(1) {
["array"]=>
array(1) {
[0]=>
string(0) ""
}
}
["myModels"]=>
array(1) {
["children[0"]=>
string(0) ""
}
}
然而,在 $_FILES
中,数组中忽略了无效字段:
<input name="good[file][0]" type="file">
<input name="myModels[postedFiles[0]]" type="file">
array(1) {
["good"]=>
array(5) {
["name"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["type"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["tmp_name"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["error"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
int(4)
}
}
["size"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
int(0)
}
}
}
}
由于我们试图获得一个物理上不可能的结构,并且文档没有明确说明应该发生什么,我们处于 未定义行为 的范围内:我们不能抱怨也不能依赖
常规 post 形式允许我们编写自己的解析器也毫无价值:
var_dump(file_get_contents('php://input'));
string(111) "good%5Barray%5D%5B0%5D=&myModels%5Bchildren%5B0%5D%5D=&good%5Bfile%5D%5B0%5D=&myModels%5BpostedFiles%5B0%5D%5D="
...但不是 multipart/form-data(又名文件)。
为什么会有这种明显的差异?我的猜测是,这是由于 $_FILES
超全局的特殊结构(恕我直言,一个来不及修复的错误设计)。使用简单名称时,您会在每片叶子的顶部获得五个自动键:
Array
(
[one] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
[two] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
一旦使用方括号,结构就会完全改变:
Array
(
[one] => Array
(
[name] => Array
(
[0] =>
)
[type] => Array
(
[0] =>
)
[tmp_name] => Array
(
[0] =>
)
[error] => Array
(
[0] => 4
)
[size] => Array
(
[0] => 0
)
)
[two] => Array
(
[name] => Array
(
[0] =>
)
[type] => Array
(
[0] =>
)
[tmp_name] => Array
(
[0] =>
)
[error] => Array
(
[0] => 4
)
[size] => Array
(
[0] => 0
)
)
)
这表明 $_POST
和 $_FILES
的内部逻辑完全不同,因此看到针对无效输入的不同解决方法并不奇怪。
我正在 PHP 中实现多用途 html 形式 posting 代码,能够 post 对象图结构。
所以我创建了一些命名规则并基于它们,我在服务器端解析索引。
其中一条规则是这样的:
<input name="myModels[children[0]]" type="text" />
当然上面的命名略有缩短,以便更容易切中要点。
当我从
中检索它们时,该命名非常有效$_POST
但是当我在文件输入中使用它时,它们从未出现在 $_FILE 全局数组中 和
print_r($_FILES);
为空
PHP supports HTML array feature even with files.
那是为什么呢?为什么这种命名方式([] inside [])适用于 POSTED 数据但不适用于文件数据。
请注意,上传文件本身不是问题。
即使使用数组,上传也很有效。即使是带有键索引的数组。
我想弄清楚的是:
<form action="/Test/uploadTest.php" method="post" enctype="multipart/form-data" >
File1 <input name="myModels[postedFiles[0]]" type="file" /></br>
File2 <input name="myModels[postedFiles[1]]" type="file" /></br>
<input type="submit" value="post" />
</form>
并在 uploadTest.php
的服务器上print_r($_FILES);
为空。
我的PHP版本有点旧,是PHP5.3.6-13。您是否认为它与我的 PHP 版本有关,或者即使在 PHP 的较新版本中也是某种错误?
提前致谢。
解决方案:@tozer83 和@alvaro 提供的答案都非常有帮助。现在事实证明,多部分形式在处理非标量索引和尝试利用文件输入的 html 数组的优势方面有所不同,以便创建用于创建复杂对象图的表达式,就像其他框架中的其他框架一样语言在 PHP 中不起作用。应该忽略 html 数组或使用其他文字(如括号)来解决此问题。 很难决定应该点击哪些复选标记!考虑到@alvoro 已经获得的高排名,我决定选择@tozer83 的答案,因为他先回答并给出了解决方案。但是@alvaro 的回答很详细,也很有帮助。所以我+1他的回答。
我尝试制作相同的表格,但做了一些修改。
<form action="uploadTest.php" method="post" enctype="multipart/form-data" >
File1 <input name="myModels[postedFiles(0)]" type="file" /></br>
File2 <input name="myModels[postedFiles(1)]" type="file" /></br>
<input type="submit" value="post" />
</form>
print_r($_FILES) 尝试上传文件时的结果:
Array ( [myModels] => Array ( [name] => Array ( [postedFiles(0)] => file1.txt [postedFiles(1)] => file2.txt ) [type] => Array ( [postedFiles(0)] => text/plain [postedFiles(1)] => text/plain ) [tmp_name] => Array ( [postedFiles(0)] => /tmp/phpiHJBb1 [postedFiles(1)] => /tmp/phpSFh4J0 ) [error] => Array ( [postedFiles(0)] => 0 [postedFiles(1)] => 0 ) [size] => Array ( [postedFiles(0)] => 4 [postedFiles(1)] => 4 ) ) )
在此处参考 PHP 手册: https://secure.php.net/manual/en/features.file-upload.post-method.php 查看示例 #3 以上传一组文件。
这似乎不起作用,但是如果文件太大,这将在您的 php.ini 到 upload_max_filesize 甚至 post_max_size.[=13= 中指定]
首先(只是为了清楚地说明)PHP 不允许非标量值作为数组键。实际上,只能使用字符串和整数。因此,没有语言结构可以容纳 myModels[postedFiles[0]]
这样的东西。 documentation about HTML arrays 并没有真正说明当无法解析的字段名称出现时会发生什么。
当我们把它推到极限时会发生什么?显然,行为因我们谈论的超全局而异。在$_POST
中,PHP尽量创建数组:
<input name="good[array][0]" type="text">
<input name="myModels[children[0]]" type="text">
array(2) {
["good"]=>
array(1) {
["array"]=>
array(1) {
[0]=>
string(0) ""
}
}
["myModels"]=>
array(1) {
["children[0"]=>
string(0) ""
}
}
然而,在 $_FILES
中,数组中忽略了无效字段:
<input name="good[file][0]" type="file">
<input name="myModels[postedFiles[0]]" type="file">
array(1) {
["good"]=>
array(5) {
["name"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["type"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["tmp_name"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
string(0) ""
}
}
["error"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
int(4)
}
}
["size"]=>
array(1) {
["file"]=>
array(1) {
[0]=>
int(0)
}
}
}
}
由于我们试图获得一个物理上不可能的结构,并且文档没有明确说明应该发生什么,我们处于 未定义行为 的范围内:我们不能抱怨也不能依赖
常规 post 形式允许我们编写自己的解析器也毫无价值:
var_dump(file_get_contents('php://input'));
string(111) "good%5Barray%5D%5B0%5D=&myModels%5Bchildren%5B0%5D%5D=&good%5Bfile%5D%5B0%5D=&myModels%5BpostedFiles%5B0%5D%5D="
...但不是 multipart/form-data(又名文件)。
为什么会有这种明显的差异?我的猜测是,这是由于 $_FILES
超全局的特殊结构(恕我直言,一个来不及修复的错误设计)。使用简单名称时,您会在每片叶子的顶部获得五个自动键:
Array
(
[one] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
[two] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
一旦使用方括号,结构就会完全改变:
Array
(
[one] => Array
(
[name] => Array
(
[0] =>
)
[type] => Array
(
[0] =>
)
[tmp_name] => Array
(
[0] =>
)
[error] => Array
(
[0] => 4
)
[size] => Array
(
[0] => 0
)
)
[two] => Array
(
[name] => Array
(
[0] =>
)
[type] => Array
(
[0] =>
)
[tmp_name] => Array
(
[0] =>
)
[error] => Array
(
[0] => 4
)
[size] => Array
(
[0] => 0
)
)
)
这表明 $_POST
和 $_FILES
的内部逻辑完全不同,因此看到针对无效输入的不同解决方法并不奇怪。