upload-interop / interface
Installs: 66
Dependents: 3
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/upload-interop/interface
Requires
- php: >=8.4
Requires (Dev)
- pds/composer-script-names: ^1.0
- pds/skeleton: ^1.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
This package is not auto-updated.
Last update: 2025-12-09 18:06:49 UTC
README
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.
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 (RFC 2119, RFC 8174).
This package attempts to adhere to the Package Development Standards approach to naming and versioning.
Interfaces
Upload-Interop defines these interfaces:
- UploadStruct represents the
$_FILESvalues for a single uploaded file. - UploadStructFactory affords creating one or more UploadStruct instances.
- UploadThrowable extends Throwable to mark an Exception as upload-related.
- UploadTypeAliases provides custom PHPStan types to aid static analysis.
UploadStruct
The UploadStruct interface represents the $_FILES values for a single
uploaded file.
-
Directives:
- Implementations MAY validate UploadStruct values; implementations doing so MUST throw an UploadThrowable when a value is invalid.
-
Notes:
-
The interface defines property hooks for
getbut notset. The interface only guarantees readability; writability is outside the scope of this package. -
The properties are in
snake_case, notcamelCase. This maintains a direct 1:1 correspondence between the native$_FILESarray keys and the 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 implementation.
-
UploadStruct Properties
-
public string $tmp_name { get; }
- Corresponds to the
'tmp_name'key in anupload_files_item_array.
- Corresponds to the
-
public int $error { get; }
- Corresponds to the
'error'key in anupload_files_item_array.
- Corresponds to the
-
public ?string $name { get; }
- Corresponds to the
'name'key in anupload_files_item_array.
- Corresponds to the
-
public ?string $full_path { get; }
- Corresponds to the
'full_path'key in anupload_files_item_array.
- Corresponds to the
-
public ?string $type { get; }
- Corresponds to the
'type'key in anupload_files_item_array.
- Corresponds to the
-
public ?int $size { get; }
- Corresponds to the
'size'key in anupload_files_item_array.
- Corresponds to the
UploadStructFactory
The UploadStructFactory affords creating one or more UploadStruct instances.
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 instance.
-
public function newUploadsFromFiles( upload_files_array $files, ) : upload_structs_array;
-
Creates an
upload_structs_arrayof UploadStruct instances parsed from anupload_files_array. -
Directives:
- Implementations MUST return an
upload_structs_arrayindex structure that corresponds to the structure in which theupload_files_arrayfields were indexed; cf. README-FILES.md.
- Implementations MUST return an
-
UploadThrowable
The UploadThrowable interface extends Throwable to mark an Exception as upload-related. It adds no class members.
UploadTypeAliases
The 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
$_FILESof up to 16 dimensions.
- A representation of
-
upload_files_group_array: array{ tmp_name:string[], error:int[], name?:string[], full_path?:string[], type?:string[], size?:int[], }- An
arrayof a group of uploaded files.
- An
-
upload_files_item_array: array{ tmp_name:string, error:int, name?:string, full_path?:string, type?:string, size?:int, }- An
arrayof a single uploaded file.
- An
-
upload_structs_array: array< array-key, UploadStruct|upload_structs_array >- An
arrayof UploadStruct instances of up to 16 dimensions.
- An
-
Notes:
-
The
upload_files_*types are defined from the$_FILESstructure. Cf. https://www.php.net/manual/en/features.file-upload.post-method.php. -
The
*_[00-0F]types are to enable limited recursion. PHPStan does not handle recursive type aliases, soupload_files_arrayandupload_structs_arraycannot 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
-
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 https://github.com/upload-interop/impl.
-
Q & A
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 instances and the various UploadTypeAliases in application or domain logic, much the same way there is cover for using DateTime or SimpleXmlElement instances in application or domain logic.
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 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.