PHPackages                             upload-interop/interface - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. upload-interop/interface

ActiveLibrary[File &amp; Storage](/categories/file-storage)

upload-interop/interface
========================

Standard interfaces for handling uploads.

1.0.0(3mo ago)2782MITPHPPHP &gt;=8.4CI passing

Since Jun 13Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/upload-interop/interface)[ Packagist](https://packagist.org/packages/upload-interop/interface)[ Docs](https://github.com/upload-interop/interface/)[ RSS](/packages/upload-interop-interface/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (5)Dependencies (4)Versions (5)Used By (2)

Upload-Interop Standard Interface Package
=========================================

[](#upload-interop-standard-interface-package)

[![PDS Skeleton](https://camo.githubusercontent.com/50d01a5094afcc3a827c3cadaec43d23b2a256cb249f5fdd6e5ffdb53ea7971c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7064732d736b656c65746f6e2d626c75652e7376673f7374796c653d666c61742d737175617265)](https://github.com/php-pds/skeleton)[![PDS Composer Script Names](https://camo.githubusercontent.com/0c17df07fd0a51ad878f1de0d4c17ea8e460f2e96ce796c8cd58e6c96ed9c08d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7064732d636f6d706f7365722d2d7363726970742d2d6e616d65732d626c75653f7374796c653d666c61742d737175617265)](https://github.com/php-pds/composer-script-names)

Upload-Interop provides an interoperable package of standard interfaces for working with upload structures in PHP 8.4+. It reflects, refines, and reconciles the common practices identified within [several pre-existing projects](./README-RESEARCH.md).

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) ([RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.txt), [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.txt)).

This package attempts to adhere to the [Package Development Standards](https://php-pds.com/) approach to [naming and versioning](https://php-pds.com/#naming-and-versioning).

Interfaces
----------

[](#interfaces)

Upload-Interop defines these interfaces:

- [*UploadStruct*](#uploadstruct) represents the `$_FILES` values for a single uploaded file.
- [*UploadStructFactory*](#uploadstructfactory) affords creating one or more [*UploadStruct*](#uploadstruct) instances.
- [*UploadThrowable*](#uploadthrowable) extends [*Throwable*](https://php.net/Throwable) to mark an [*Exception*](https://php.net/Exception) as upload-related.
- [*UploadTypeAliases*](#uploadtypealiases) provides custom PHPStan types to aid static analysis.

### *UploadStruct*

[](#uploadstruct)

The [*UploadStruct*](#uploadstruct) interface represents the `$_FILES` values for a single uploaded file.

- Directives:

    - Implementations MAY validate [*UploadStruct*](#uploadstruct) values; implementations doing so MUST throw an [*UploadThrowable*](#uploadthrowable) when a value is invalid.
- Notes:

    - **The interface defines property hooks for `get` but not `set`.** The interface only guarantees readability; writability is outside the scope of this package.
    - **The properties are in `snake_case`, not `camelCase`.** This maintains a direct 1:1 correspondence between the native `$_FILES` array keys and the [*UploadStruct*](#uploadstruct) properties.
    - **There are no affordances for operating on the uploaded file itself.**Reading from, writing to, moving, copying, renaming, etc. an uploaded file are application-specific concerns, independent from any specific [*UploadStruct*](#uploadstruct) implementation.

#### *UploadStruct* Properties

[](#uploadstruct-properties)

- ```
    public string $tmp_name { get; }
    ```

    - Corresponds to the `'tmp_name'` key in an `upload_files_item_array`.
- ```
    public int $error { get; }
    ```

    - Corresponds to the `'error'` key in an `upload_files_item_array`.
- ```
    public ?string $name { get; }
    ```

    - Corresponds to the `'name'` key in an `upload_files_item_array`.
- ```
    public ?string $full_path { get; }
    ```

    - Corresponds to the `'full_path'` key in an `upload_files_item_array`.
- ```
    public ?string $type { get; }
    ```

    - Corresponds to the `'type'` key in an `upload_files_item_array`.
- ```
    public ?int $size { get; }
    ```

    - Corresponds to the `'size'` key in an `upload_files_item_array`.

### *UploadStructFactory*

[](#uploadstructfactory)

The [*UploadStructFactory*](#uploadstructfactory) affords creating one or more [*UploadStruct*](#uploadstruct)instances.

#### *UploadStructFactory* Methods

[](#uploadstructfactory-methods)

- ```
    public function newUpload(
        string $tmp_name,
        int $error,
        ?string $name = null,
        ?string $full_path = null,
        ?string $type = null,
        ?int $size = null,
    ) : UploadStruct;
    ```

    - Creates a single [*UploadStruct*](#uploadstruct) instance.
- ```
    public function newUploadsFromFiles(
        upload_files_array $files,
    ) : upload_structs_array;
    ```

    - Creates an `upload_structs_array` of [*UploadStruct*](#uploadstruct) instances parsed from an `upload_files_array`.
    - Directives:

        - Implementations MUST return an `upload_structs_array` index structure that corresponds to the structure in which the `upload_files_array` fields were indexed; cf. [README-FILES.md](./README-FILES.md).

### *UploadThrowable*

[](#uploadthrowable)

The [*UploadThrowable*](#uploadthrowable) interface extends [*Throwable*](https://php.net/Throwable) to mark an [*Exception*](https://php.net/Exception) as upload-related. It adds no class members.

### *UploadTypeAliases*

[](#uploadtypealiases)

The [*UploadTypeAliases*](#uploadtypealiases) interface provides custom PHPStan types to aid static analysis.

- ```
    upload_files_array: array<
        array-key,
        upload_files_item_array|upload_files_group_array|upload_files_array
    >

    ```

    - A representation of `$_FILES` of up to 16 dimensions.
- ```
    upload_files_group_array: array{
        tmp_name:string[],
        error:int[],
        name?:string[],
        full_path?:string[],
        type?:string[],
        size?:int[],
    }

    ```

    - An `array` of a group of uploaded files.
- ```
    upload_files_item_array: array{
        tmp_name:string,
        error:int,
        name?:string,
        full_path?:string,
        type?:string,
        size?:int,
    }

    ```

    - An `array` of a single uploaded file.
- ```
    upload_structs_array: array<
        array-key,
        UploadStruct|upload_structs_array
    >

    ```

    - An `array` of [*UploadStruct*](#uploadstruct) instances of up to 16 dimensions.
- Notes:

    - **The `upload_files_*` types are defined from the `$_FILES` structure.**Cf. .
    - **The `*_[00-0F]` types are to enable limited recursion.** PHPStan does not handle recursive type aliases, so `upload_files_array` and `upload_structs_array` cannot ever refer back to themselves. As a result, those type aliases refer to the `*_[00-0F]` types to enable recursion to 16 dimensions. Consumers need not use these recursion-enabling type aliases.

Implementations
---------------

[](#implementations)

- Directives:

    - Implementations advertised as readonly or immutable MUST be deeply readonly or immutable; they MUST NOT encapsulate any references, resources, mutable objects, objects or arrays encapsulating references or resources or mutable objects, and so on.
    - Implementations MAY define additional class members not defined in these interfaces; implementations advertised as readonly or immutable MUST make those additional class members deeply readonly or immutable.
- Notes:

    - **Reflection does not invalidate advertisements of readonly or immutable implementations.** The ability of a consumer to use Reflection to mutate an implementation advertised as readonly or immutable does not constitute a failure to comply with Upload-Interop.
    - **Reference implementations** are available at .

Q &amp; A
---------

[](#q--a)

### Why a separate Upload-Interop?

[](#why-a-separate-upload-interop)

Whereas the key structures of `$_GET`, `$_POST`, etc. superglobal arrays are not well-defined, the terminating `upload_files_array_item` data structure in the `$_FILES` superglobal **is** well-defined. However, one wants to be able to pass that data structure (or a representation of it) into presentation-independent application or domain logic. As such, one would prefer something that is not tied to a particular presentation format.

For example, embedding the Upload-Interop structures in an HTTP-related standard could reasonably be considered to be tying the structures to the HTTP presentation format. That in turn would make Upload-Interop academically unsuitable for application or domain use.

Thus, Upload-Interop being separated from a particular presentation format gives philosophical cover to using [*UploadStruct*](#uploadstruct) instances and the various [*UploadTypeAliases*](#uploadtypealiases) in application or domain logic, much the same way there is cover for using [*DateTime*](https://www.php.net/manual/en/class.datetime.php) or [*SimpleXmlElement*](https://www.php.net/manual/en/class.simplexmlelement.php) instances in application or domain logic.

### Why is there no *UploadCollection* ?

[](#why-is-there-no-uploadcollection-)

`$_GET` and `$_POST` user inputs are arbitrarily structured from interaction to interaction. Except for the terminating `upload_files_array_item`, the `$_FILES` user inputs are likewise arbitrarily structured. An `upload_structs_array` is a representation of that arbitrary structure.

As with other user inputs, it is an application-specific concern to map those arbitrary structures to more well-defined ones, such as domain-specific collections.

### Why is it an *Upload*Struct** and not just an *Upload* ?

[](#why-is-it-an-uploadstruct-and-not-just-an-upload-)

Upload-Interop wants to avoid *Interface* suffixes, and wants to avoid making implementors use import aliases. Calling it an *Upload* would mean any implementation also called *Upload* would have to alias the interop interface. It is the difference between this less-preferable alternative ...

```
use UploadInterop\Interface\Upload as UploadInteropInterface;

class Upload implements UploadInteropInterface
{
    // ...
}
```

... and this more-preferable one:

```
use UploadInterop\Interface\UploadStruct;

class Upload implements UploadStruct
{
    // ...
}
```

Further, the interface is struct-like in that it is composed only of properties.

It is true that none of the researched implementations use *Struct* in their naming; but then, the interop is for the interface, so existing implementation names can remain as they are.

---

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance78

Regular maintenance activity

Popularity14

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~55 days

Total

5

Last Release

119d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/25754?v=4)[Paul M. Jones](/maintainers/pmjones)[@pmjones](https://github.com/pmjones)

---

Top Contributors

[![pmjones](https://avatars.githubusercontent.com/u/25754?v=4)](https://github.com/pmjones "pmjones (23 commits)")

---

Tags

filesstandardupload

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/upload-interop-interface/health.svg)

```
[![Health](https://phpackages.com/badges/upload-interop-interface/health.svg)](https://phpackages.com/packages/upload-interop-interface)
```

###  Alternatives

[uploadcare/uploadcare-php

Uploadcare PHP integration handles uploads and further operations with files by wrapping Upload and REST APIs.

1022.5M6](/packages/uploadcare-uploadcare-php)[unclecheese/dropzone

An HTML5 upload field for the CMS and frontend forms.

46130.7k6](/packages/unclecheese-dropzone)[vova07/yii2-fileapi-widget

The FileAPI widget for Yii2 framework.

4765.5k9](/packages/vova07-yii2-fileapi-widget)[delight-im/file-upload

Simple and convenient file uploads — secure by default

7210.7k2](/packages/delight-im-file-upload)[floor12/yii2-module-files

Yii2 module to upload and manage files to your models.

1612.4k6](/packages/floor12-yii2-module-files)[gaspertrix/laravel-backpack-dropzone-field

Add Dropzone support for Laravel Backpack

172.2k](/packages/gaspertrix-laravel-backpack-dropzone-field)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
