Oihana PHP

zip

Table of Contents

Functions

assertZip()  : bool
Validates that a file is a zip archive.
hasZipExtension()  : bool
Checks if a file has a zip-related extension.
hasZipMimeType()  : bool
Checks if a file has a zip-related MIME type.
unzip()  : true|array<string|int, string>
Extracts a zip archive into a destination directory.
validateZipStructure()  : bool
Validates the internal structure of a zip file.
zip()  : string
Creates a zip archive from one or more files and/or directories.
zipDirectory()  : string
Creates a zip archive from a directory.
zipFileInfo()  : array{isValid?: bool, extension?: string, mimeType?: string|null, compression?: string|null, fileCount?: int|null, totalSize?: int|null}
Retrieves detailed information about a zip archive file.

Functions

assertZip()

Validates that a file is a zip archive.

assertZip(string $filePath[, bool $strictMode = false ]) : bool
Parameters
$filePath : string

Path to the file to validate.

$strictMode : bool = false

If true, performs deep validation using file contents (see validateZipStructure()). If false, only checks the extension and the basic MIME type.

Tags
throws
FileException

If the file does not exist or cannot be read.

author

Marc Alcaraz (ekameleon)

since
1.2.0
example

Basic validation using file extension and MIME type:

$isValid = assertZip('/path/to/archive.zip');

Strict validation with file content inspection:

$isValid = assertZip('/path/to/archive.zip', true);
Return values
bool

True if the file is a valid zip archive, false otherwise.

hasZipExtension()

Checks if a file has a zip-related extension.

hasZipExtension(string $filePath[, array<string|int, string> $zipExtensions = [FileExtension::ZIP] ]) : bool
Parameters
$filePath : string

Path to the file.

$zipExtensions : array<string|int, string> = [FileExtension::ZIP]

Optional list of valid zip-related extensions. Defaults to the single .zip extension.

Tags
author

Marc Alcaraz (ekameleon)

since
1.2.0
example

Check a simple zip file:

var_dump( hasZipExtension('/path/to/archive.zip') ); // bool(true)

Check is case-insensitive:

var_dump( hasZipExtension('/path/to/ARCHIVE.ZIP') ); // bool(true)

Check a file with an unsupported extension:

var_dump( hasZipExtension('/path/to/archive.tar') ); // bool(false)
Return values
bool

True if the file has a recognized zip extension.

hasZipMimeType()

Checks if a file has a zip-related MIME type.

hasZipMimeType(string $filePath[, array<string|int, string> $mimeTypes = ['application/zip', 'application/x-zip', 'application/x-zip-compressed', 'application/zip-compressed', 'multipart/x-zip'] ]) : bool

This function inspects the MIME type of the given file against a list of valid zip-related MIME types to determine if the file is a zip archive.

It is a thin wrapper around hasMimeType() pre-configured with the common zip MIME types.

Parameters
$filePath : string

Path to the file.

$mimeTypes : array<string|int, string> = ['application/zip', 'application/x-zip', 'application/x-zip-compressed', 'application/zip-compressed', 'multipart/x-zip']

Optional list of valid zip MIME types. Defaults to common zip types:

  • 'application/zip'
  • 'application/x-zip'
  • 'application/x-zip-compressed'
  • 'application/zip-compressed'
  • 'multipart/x-zip'
Tags
author

Marc Alcaraz (ekameleon)

since
1.2.0
example

Check if a .zip file is a zip archive:

$result = hasZipMimeType('/path/to/archive.zip');
var_dump($result); // bool(true) or bool(false)

Check a non-existent file (returns false):

$result = hasZipMimeType('/path/to/missing.zip');
var_dump($result); // bool(false)
Return values
bool

True if the file exists and its MIME type matches one of the given zip MIME types.

unzip()

Extracts a zip archive into a destination directory.

unzip(string $zipFile, string $outputPath[, array{dryRun?: bool, overwrite?: bool, maxEntries?: int|null, maxSize?: int|null, keepPermissions?: bool} $options = [] ]) : true|array<string|int, string>

This function mirrors untar(). It guards against path traversal (Zip Slip) and decompression bombs, can preview the contents without writing anything (dry run), and can refuse to overwrite existing files.

Parameters
$zipFile : string

Path to the zip archive to extract.

$outputPath : string

Directory where the archive is extracted. Created if missing.

$options : array{dryRun?: bool, overwrite?: bool, maxEntries?: int|null, maxSize?: int|null, keepPermissions?: bool} = []

Optional flags, keyed by ZipOption:

  • dryRun: If true, no file is written; returns the list of file entries that would be extracted (directory entries excluded). Default: false.
  • overwrite: If false, extraction fails when a target file already exists. Default: true.
  • maxEntries: If a positive integer, the archive is rejected when it declares more entries than this limit (decompression-bomb guard). Default: null (no limit).
  • maxSize: If a positive integer, the archive is pre-scanned and rejected before any file is written when the sum of the entries' uncompressed sizes exceeds this limit (decompression-bomb guard). Default: null (no limit).
  • keepPermissions: If true, restores the Unix file mode stored in each entry's external attributes (OPSYS_UNIX) via chmod(). Entries without Unix permissions are left with the default mode. Best-effort: a failing chmod() is ignored. Default: false.
Tags
throws
FileException

If the archive does not exist, cannot be opened, an entry escapes the destination (Zip Slip), a bomb guard trips, or a target already exists while overwrite is disabled.

DirectoryException

If the destination directory (or an entry's parent) cannot be created.

example
// Basic extraction
unzip( '/path/to/archive.zip' , '/output/dir' );

// Dry-run: preview contents without extracting
$files = unzip( '/path/to/archive.zip' , '/output/dir' , [ 'dryRun' => true ] );

// Refuse to overwrite, and guard against decompression bombs
unzip( '/path/to/archive.zip' , '/output/dir' , [
    'overwrite'  => false,
    'maxEntries' => 10_000,
    'maxSize'    => 500 * 1024 * 1024,
]);
author

Marc Alcaraz (ekameleon)

since
1.2.0
Return values
true|array<string|int, string>

Returns true on successful extraction, or the list of file entries (relative to the archive root) when dryRun is enabled.

validateZipStructure()

Validates the internal structure of a zip file.

validateZipStructure(string $filePath) : bool

This function checks whether the given file is a valid, readable zip archive. It uses the ZipArchive class to attempt opening the archive and inspects a few entries to confirm structural integrity.

Parameters
$filePath : string

Path to the zip file.

Tags
author

Marc Alcaraz (ekameleon)

since
1.2.0
example
var_dump( validateZipStructure( '/path/to/archive.zip'  ) ); // true or false
var_dump( validateZipStructure( '/path/to/invalid.zip'  ) ); // false
var_dump( validateZipStructure( '/path/to/not_a_zip.txt') ); // false
var_dump( validateZipStructure( '/nonexistent/file.zip' ) ); // false
Return values
bool

True if the file has a valid zip structure, false otherwise.

zip()

Creates a zip archive from one or more files and/or directories.

zip(string|array<string|int, string> $paths[, string|null $outputPath = null ][, string|null $compression = CompressionType::ZIP ][, string|null $preserveRoot = null ]) : string

This function supports adding multiple paths (files or directories) to a zip archive, with a per-entry compression method. It can preserve the root directory structure inside the archive, and generates a unique temporary archive if no output path is specified.

Empty directories are preserved in the archive.

Parameters
$paths : string|array<string|int, string>

Absolute path(s) to file(s) or directory(ies) to include in the archive.

$outputPath : string|null = null

Optional full path to the final archive file to create. If null, an automatic unique filename with timestamp is generated in the system temp directory.

$compression : string|null = CompressionType::ZIP

Per-entry compression method. Supported values are CompressionType::ZIP (DEFLATE, the default) and CompressionType::NONE (stored, no compression).

$preserveRoot : string|null = null

If set, paths inside the archive will be stored relative to this directory, allowing to preserve directory structure when extracting. Must be an absolute path.

Tags
throws
FileException

If any of the provided paths does not exist, or if the archive file cannot be created.

UnsupportedCompressionException

If the requested compression method is not supported for zip archives.

DirectoryException

If the temporary directory cannot be created or accessed.

RuntimeException

If no files are added to the archive.

see
CompressionType
example

Archive a single file, auto-named, DEFLATE compressed (default):

$zipPath = zip('/var/www/html/index.php');

Archive a directory without compression (stored):

$zipPath = zip('/var/www/html', '/tmp/site.zip', CompressionType::NONE);

Archive multiple files:

$zipPath = zip(['/etc/hosts', '/etc/hostname'], '/tmp/config.zip');

Archive directory with root preserved (relative paths):

$zipPath = zip('/var/www/html/project', '/tmp/project.zip', CompressionType::ZIP, '/var/www/html/project');
author

Marc Alcaraz (ekameleon)

since
1.2.0
Return values
string

Returns the full path to the created zip archive file.

zipDirectory()

Creates a zip archive from a directory.

zipDirectory(string $directory[, string|null $compression = CompressionType::ZIP ][, string|null $outputPath = null ][, array<string|int, mixed> $options = [] ]) : string

This function creates a zip archive from the given directory. It supports filtering files by exclude patterns, by a callback filter function, and adding optional metadata saved as .metadata.json inside the archive.

If no filters or metadata are provided, it simply creates the archive directly from the directory (preserving its root). Otherwise, it copies the filtered files to a temporary directory and archives from there.

Parameters
$directory : string

The source directory to archive.

$compression : string|null = CompressionType::ZIP

Per-entry compression method (CompressionType::ZIP — DEFLATE, default — or CompressionType::NONE — stored).

$outputPath : string|null = null

Optional output archive path. If null, defaults to the directory name plus the .zip extension.

$options : array<string|int, mixed> = []

Additional options:

  • exclude => string[] list of glob patterns or file names to exclude
  • filter => callable|null a function (string $filepath): bool
  • metadata => array<string, string> extra metadata to embed in .metadata.json
Tags
throws
DirectoryException

If the source directory does not exist or is inaccessible.

FileException

If there are issues writing files or archives.

UnsupportedCompressionException

If an unsupported compression method is specified.

RuntimeException

If no files match the filtering criteria.

example
// Create a zip archive from directory /var/www/html
$archive = zipDirectory('/var/www/html');
echo $archive; // /var/www/html.zip

// Create a stored (uncompressed) archive, excluding .git and node_modules
$archive = zipDirectory(
    '/var/www/html',
    CompressionType::NONE,
    null,
    [ ZipOption::EXCLUDE => ['.git', 'node_modules'] ]
);

// Create an archive with a custom filter callback and embedded metadata
$archive = zipDirectory(
    '/var/www/html',
    CompressionType::ZIP,
    '/backups/html_backup.zip',
    [
        ZipOption::FILTER   => fn( string $filePath ): bool => str_ends_with( $filePath , '.php' ),
        ZipOption::METADATA => [ 'createdBy' => 'admin' , 'description' => 'PHP source backup' ],
    ]
);
author

Marc Alcaraz (ekameleon)

since
1.2.0
Return values
string

Returns the full path to the created archive file.

zipFileInfo()

Retrieves detailed information about a zip archive file.

zipFileInfo(string $filePath[, bool $strictMode = false ]) : array{isValid?: bool, extension?: string, mimeType?: string|null, compression?: string|null, fileCount?: int|null, totalSize?: int|null}

This function inspects the given zip file to determine its validity, MIME type, compression family, number of contained entries, and total uncompressed size.

It uses the ZipArchive class to count entries and sum their uncompressed sizes when the archive is valid.

Parameters
$filePath : string

Absolute path to the zip archive file to inspect.

$strictMode : bool = false

When true, enables strict validation of the zip structure via assertZip(). Default is false for a more lenient check.

Tags
throws
FileException

If the provided file does not exist or is not accessible.

see
assertZip()
author

Marc Alcaraz (ekameleon)

since
1.2.0
example
$info = zipFileInfo( '/archives/sample.zip' );
print_r( $info );

$info = zipFileInfo( '/bad/path.zip' );
var_dump( $info['isValid'] ); // false

// Strict mode
$info = zipFileInfo( '/archives/sample.zip' , true );
Return values
array{isValid?: bool, extension?: string, mimeType?: string|null, compression?: string|null, fileCount?: int|null, totalSize?: int|null}

Returns an associative array keyed by ZipInfo with:

  • isValid: Whether the file is a valid zip according to assertZip().
  • extension: File extension (lowercase) extracted from the path.
  • mimeType: MIME type detected via finfo.
  • compression: CompressionType::ZIP when the MIME type is zip-like, otherwise CompressionType::NONE.
  • fileCount: Number of entries inside the archive (if valid), otherwise null.
  • totalSize: Sum of the uncompressed sizes (in bytes) of all entries (if valid), otherwise null.
On this page

Search results