我正在用PHP实现一个多用途的html表单发布代码,该代码能够发布对象图结构
因此,我创建了一些命名规则,并基于它们在服务器端解析索引
其中一条规则是这样的:
<input name="myModels[children[0]]" type="text" />
当然,上面的命名稍微缩短了一点,以便于切中要害
当我从检索到它们时,这种命名非常有效
$_POST
但是当我在文件输入中使用它时,它们永远不会出现在$_file全局数组中和
print_r($_FILES);
是空的
根据文件上传php手册
PHP支持HTML数组功能,甚至支持文件。
那为什么呢?为什么这种类型的命名([]内部的[])适用于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版本有点旧,是PHP 5.3.6-13。你认为这是我的PHP版本的问题吗?还是在新版本的PHP中也有一些bug
提前谢谢。
解决方案:@tozer83和@alvaro提供的答案都很有帮助。现在,事实证明,多部分表单在处理非标量索引和试图利用带有文件输入的html数组的优势来创建用于创建复杂对象图的表达式方面有一些不同,就像其他语言中的其他框架一样,这在PHP中是行不通的。应该忽略html数组或使用括号等其他文字来解决此问题。很难决定应该点击哪一个复选标记!考虑到@alvoro已经获得了这么高的排名,我决定选择@tozer83的答案,因为他首先回答并给出了解决方案。但@alvaro的回答很详细,也很有帮助。所以我+1他的答案。
首先(只是为了澄清)PHP不允许非标量值作为数组键。事实上,只能使用字符串和整数。因此,没有一种语言结构可以容纳像myModels[postedFiles[0]]
这样的东西。关于HTML数组的文档并没有真正说明当不可解析的字段名出现时会发生什么
当我们把它推到极限时会发生什么?显然,行为是不同的,这取决于我们谈论的超全球。在$_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="
但不是多部分/表单数据(又称文件)。
为什么会出现这种明显的差异?我的猜测是,这是由于$_FILES
超全局的特殊结构(IMHO,一种为时已晚的错误设计)。当使用简单的名称时,你会在每片叶子的顶部获得五个自动键:
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
中的内部逻辑完全不同,因此在无效输入上看到不同的解决方案并不奇怪。
我试图制作相同的表单,但做了一些修改。
<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来指定。