支持Laravel.io的持续发展 →

Laravel中验证文件上传数组

30 Jun, 2022 3 min read

假设你有一个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包含所有空的文件对象,但每个对象都有一个设置为4error值,该值与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',
    ]
]

通过为主数组配对一组规则以及使用点表示法为每个数组元素设置规则,我们可以得到我们想要的验证行为。

最后更新时间:1年前。

driesvints, marketopiateam, bumbar, davidagoua 喜欢了这篇文章

4
喜欢这篇文章? 告诉作者,给他们一个掌声!
joelclermont (Joel Clermont) 我帮助Laravel SaaS团队开发更好的产品。播客请访问show.nocompromises.io。作者:masteringlaravel.io

你可能还喜欢这些文章

2024年3月11日

如何使用Larastan将你的Laravel应用从0升级到9

在Laravel应用执行之前发现错误是可能的,这要归功于Larastan,它是一个...

阅读文章
2024年7月19日

在没有特性模式下标准化API响应

我注意到大多数用于API响应的库都是使用特性实现的,并且...

阅读文章
2024年7月17日

通过Laravel项目中的Discord通知收集反馈

如何在Laravel项目中创建反馈模块,并在收到消息时收到Discord通知...

阅读文章

我们想感谢这些 优秀的公司 对我们的支持

在这里放置您的标志?

Laravel.io

The Laravel问题解决、知识分享和社区建设的门户网站。

© 2024 Laravel.io - 版权所有。