假设你有一个HTML表单,包含3个名为certificate[]
的文件输入框,并且你想要使它们全部为必填项。这应该很容易,对吧?
一个合理的方法可能是在你的验证规则中使用数组点表示法。
<?php
$rules = [
'certificate.*' => [
'required',
],
];
但这不起作用。为什么?如果文件上传为空,它甚至不是由你的规则验证的Laravel Request
的一部分。certificate.*
规则意味着“对于证书数组中的每个元素,该元素都应该是必填的”,但如果certificate
在你请求中不存在,那么这个规则就会通过。
让我们找出发生了什么。首先检查的是浏览器做什么?也许即使文件上传为空,它也不会将其表单字段作为其请求的一部分发送。检查我的浏览器的网络选项卡,我看到表单字段确实存在。
接下来,关于PHP呢?是否会将空文件包含在$_FILES
超全局变量中?当然,$_FILES
包含一个包含3个元素的certificate
数组,每个元素对应我每个空文件输入框。
array:1 [▼
"certificate" => array:5 [▼
"name" => array:3 [▶]
"type" => array:3 [▶]
"tmp_name" => array:3 [▶]
"error" => array:3 [▶]
"size" => array:3 [▶]
]
]
让我们还添加一个包含3个空文本输入框的数组name[]
,并查看Laravel的Request
对象。
// output of $request->input()
array:2 [▼
"_token" => "eSGJ05lCLWLFZ1zCGxlP2rYxgy7FyZT6Yg8Fjawa"
"name" => array:3 [▼
0 => null
1 => null
2 => null
]
]
// output of $request->file()
[]
因此,在请求中存在一个空文本字段的数组,但我们的空文件输入数组却无处可寻。为什么它消失了?
如果我们深入了解请求是如何创建的,我们会找到我们的答案。当请求初始化时,它会传递所有PHP提供的超全局变量,如$_GET
、$_POST
、$_FILES
等。在内部,那个$_FILES
参数被初始化为一个Symfony FileBag
对象。当那个FileBag
被初始化时,每个元素都会通过convertFileInformation
函数传递。在许多其他的事情中,它会将这个数组重构为一个更一致的形状,但请注意以下相关代码。
<?php
if (\UPLOAD_ERR_NO_FILE == $file['error']) {
$file = null;
} else {
$file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false);
}
尽管PHP中的$_FILES
包含所有空的文件对象,但每个对象都有一个设置为4
的error
值,该值与UPLOAD_ERR_NO_FILE
常量匹配,因此初始化的FileBag
为空。最后,我们找到了它!这就是那些文件消失的地方!
我相信你和我一样对此感到有趣,但让我们回到原始的验证场景。我们有一个包含3个文件输入数组的形式,我们希望它们都为必填项。我们该如何做呢?
<?php
$rules = [
'certificate' => [
'required',
'array',
'size:3',
],
'certificate.*' => [
// any other sort of file validation we want to do on each element
'file',
'mimes:pdf',
'size:4096',
]
]
通过为主数组配对一组规则以及使用点表示法为每个数组元素设置规则,我们可以得到我们想要的验证行为。
driesvints, marketopiateam, bumbar, davidagoua 喜欢了这篇文章