WPCMF

Laravel 中验证文件上传数组

假设您有一个带有 3 个名为 的文件输入的 HTML 表单certificate[],并且您想让它们都成为必需的。应该很容易吧?

一种合理的方法可能是在验证规则中使用数组点表示法:

<?php
$rules = [
    'certificate.*' => [
        'required',
    ],
];

然而,这并没有按预期工作。为什么?如果文件上传是空的,那么它甚至不是 Laravel 的一部分Request,可以通过你的规则进行验证。该certificate.*规则的意思是“对于证书数组中的每个元素,该元素都应该是必需的”,但如果certificate您的 甚至不存在该元素Request,则该规则将通过。

让我们弄清楚发生了什么。首先要检查:浏览器在做什么?如果文件上传为空,它甚至可能不会在其请求中发送表单字段。检查浏览器的网络选项卡,我发现表单字段确实存在。

接下来,PHP 呢?它是否包含$_FILES超全局中的空文件?果然,$_FILES包含一个包含certificate3 个元素的数组,一个用于我的每个空文件输入:

array:1 [▼
  "certificate" => array:5 [▼
    "name" => array:3 [▶]
    "type" => array:3 [▶]
    "tmp_name" => array:3 [▶]
    "error" => array:3 [▶]
    "size" => array:3 [▶]
  ]
]

让我们添加一个包含 3 个空文本输入的数组,name[]并查看 LaravelRequest对象:

// output of $request->input()
array:2 [▼
  "_token" => "eSGJ05lCLWLFZ1zCGxlP2rYxgy7FyZT6Yg8Fjawa"
  "name" => array:3 [▼
    0 => null
    1 => null
    2 => null
  ]
]

// output of $request->file()
[]

因此,请求中存在一个空文本字段数组,但我们的空文件输入数组却无处可寻。为什么会消失?

如果我们深入研究 aRequest是如何创建的,我们就会找到答案。当 aRequest被初始化时,它被传入所有 PHP 提供的超级全局变量,如$_GET$_POST$_FILES等等。在内部,该$_FILES参数被初始化为 SymfonyFileBag对象。初始化时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,但它们中的每一个都有一个error设置为 的值4,它与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',
    ]
]

通过在主数组上配对一组规则以及使用点符号为每个数组元素设置规则,我们得到了我们想要的验证行为

 

标签:

推荐

上一篇:如何在 Excel 中编写宏:宏教程 – 什么是 & 使用

下一篇:Laravel 8 从数据库获取最近30天的记录

猜你喜欢

微信咨询

添加专属客服

一对一为您答疑解惑 添加客服微信 立即扫码添加我吧
扫码QQ

扫码QQ联系

立即扫码添加我吧