tvanc / files-array-organizer
创建一个有组织的 $_FILES 数组版本。
Requires
- php: ^7.3
Requires (Dev)
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2024-09-21 09:40:31 UTC
README
处理 PHP 中的 $_FILES
数组很糟糕。大多数解决方案仅适用于特定情况,且不易移植。此实用程序旨在将任何可能的 $_FILES
数组组织成您直观期望的结构。获取上传文件的信息应该像读取 $_POST
数组一样简单。
入门指南
需求
PHP >= 7.3
安装
composer require tvanc/files-array-organizer
示例
一个输入,一个文件
在这种情况下,$_FILES
数组非常直观,有组织的版本与未组织的版本相同。
<?php use tvanc\FilesArrayOrganizer\FilesArrayOrganizer; if ($_FILES) { $organizedFiles = FilesArrayOrganizer::organize($_FILES); if ($organizedFiles === $_FILES) { echo "Looks like you didn't really need to do that."; } } ?> <form method="post" enctype="multipart/form-data"> <input type="file" name="file"> <button>Submit</button> </form>
单个输入可以接受多个文件
FilesArrayOrganizer
使得处理这种常见情况变得稍微容易一些。
<?php use tvanc\FilesArrayOrganizer\FilesArrayOrganizer; if ($_FILES) { $organizedFiles = FilesArrayOrganizer::organize($_FILES); $attachments = $organizedFiles['attachments']; foreach ($attachments as $attachment) { $attachment_name = $attachment['name']; $attachment_size = $attachment['size']; } } ?> <form method="post" enctype="multipart/form-data"> <!-- Notice this input accepts multiple files --> <input type="file" name="attachments[]" multiple> <button>Submit</button> </form>
多个输入可以接受多个文件
FilesArrayOrganizer
使得处理这种不太常见的场景 大大 变得容易。查看 解释 以查看来自包含多个输入(每个输入都可以接受多个文件)的表单的令人惊讶的 $_FILES
数组。
<?php use tvanc\FilesArrayOrganizer\FilesArrayOrganizer; // @var Todo[] $todos An array of todos $todos = fetchTodos(); if ($_FILES) { $organizedFiles = FilesArrayOrganizer::organize($_FILES); foreach ($organizedFiles as $index => $postedTodo) { $attachments = $organizedFiles['todo'][$index]; saveAttachments($index, $attachments); } } ?> <form method="post" enctype="multipart/form-data"> <?php foreach ($todos as $index => $todo) { ?> <label>Attachments for todo <?= $index ?></label> <input type="file" name="todo[<?= $index ?>][attachments][]" multiple > <?php } ?> <button>Submit</button> </form>
对每个文件执行自定义回调
为了改变文件数据的表示方式,将回调函数作为 FilesArrayOrganizer::organize()
的第二个参数传递。回调函数接收一个参数,即文件数据数组。回调函数的返回值将用于表示文件,而不是接收到的数组参数。
<?php use tvanc\FilesArrayOrganizer\FilesArrayOrganizer; use YourOwn\MadeUpNameSpace\UploadedFile; // Receive $file by reference to mutate it. You can even replace it entirely. $callback = function (array & $file) { $file = new UploadedFile($file); } $organizedFilesArray = FilesArrayOrganizer::organize($_FILES, $callback); // $attachments will be an array of UploadedFile objects $attachments = $organizedFilesArray['attachments']; ?> <form method="post" enctype="multipart/form-data"> <input type="file" name="attachments[]" multiple> <button>Submit</button> </form>
解释
对于某些情况,处理 $_FILES
超全局变量是可以的。通过名为 attachment
的字段上传单个文件将生成一个简单的 $_FILES
数组,如下所示
[ 'attachment' = [ 'name' => 'filename.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/phpR4nD0m', 'error' => 0, 'size' => 2407, ] ]
获取文件的属性很简单。输入值的路径对应于输入字段的名称。
$file_name = $_FILES['attachment']['name']; $file_size = $_FILES['attachment']['size'];
那么名为 todo[0][attachments][]
的字段呢,它可以接受多个文件?处理这个字段的文件应该是很容易的。对吧?
<?php $attachments = $_FILES['todo'][0]['attachments']; foreach ($attachments as $attachment) { doSomething($attachment); } ?> <form method="post" enctype="multipart/form-data"> <input type="file" name="todo[0][attachments][]" multiple> </form>
错了。
你认为 $_FILES
数组会看起来像这样。
[ 'todo' => [ 0 => [ 'attachments' => [ 0 => [ 'name' => 'filename.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/phpR4nD0m', 'error' => 0, 'size' => 2407, ], // ... ], ], ] ]
实际上它会看起来像这样
[ 'todo' => [ 'name' => [ 0 => [ 'attachments' => [ 0 => 'filename.jpg' ] ] ], 'type' => [ 0 => [ 'attachments' => [ 0 => 'image/jpeg' ] ] ], 'tmp_name' => [ 0 => [ 'attachments' => [ 0 => '/tmp/phpKYBy4z' ] ] ], 'error' => [ 0 => [ 'attachments' => [ 0 => 0 ] ] ], 'size' => [ 0 => [ 'attachments' => [ 0 => 2407 ] ] ] ] ]
我将留作读者的练习,去找出如何从中提取有用的信息。如果您不想每次需要同时处理多个文件时都重复这个练习,只需使用这个库。
要查看如何使用与这种 $_FILES
数组类似的 FilesArrayOrganizer
,请参阅示例,多个输入可以接受多个文件。