Skip to content

Instantly share code, notes, and snippets.

@ajaxray
Created March 23, 2024 08:36
Show Gist options
  • Save ajaxray/9835109ab15e11a17a72f8f664860b5f to your computer and use it in GitHub Desktop.
Save ajaxray/9835109ab15e11a17a72f8f664860b5f to your computer and use it in GitHub Desktop.
Make Zip Archive of a directory (including all files in it recursively) in PHP
<?php
namespace App\Services;
class ZipDirectory
{
public function __construct(
private string $sourcePath,
private ?string $outputPath = null,
)
{
$this->sourcePath = realpath($this->sourcePath);
if(!is_dir($this->sourcePath)) {
throw new \InvalidArgumentException($this->sourcePath . ' is not a directory!');
}
if (is_null($this->outputPath)) {
$this->outputPath = $this->sourcePath. '.zip';
}
return $this;
}
/**
* @return string Output zip file path
*/
public function make(bool $removeSourceOnSuccess = false): string
{
$zip = new \ZipArchive();
if ($zip->open($this->outputPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) === TRUE) {
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($this->sourcePath),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
// Skip directories (they would be added automatically)
if (!$file->isDir()) {
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($this->sourcePath) + 1);
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}
// Zip archive will be created only after closing object
if ($zip->close()) {
if ($removeSourceOnSuccess) {
system('rm -rf ' . escapeshellarg($this->sourcePath));
}
return $this->outputPath;
}
throw new \RuntimeException("Failed to make zip file at ({$this->outputPath}).");
} else {
throw new \RuntimeException("Could not open zip file for writing.");
}
}
}
@ajaxray
Copy link
Author

ajaxray commented Mar 23, 2024

How to use?

$targetDir = '/path/to/TargetDir';
$zipPath = (new ZipDirectory($targetDir))->make();
// $zipPath should be: /path/to/TargetDir.zip

$outputPath = '/path/to/another/location/output.zip';
$zipPath = (new ZipDirectory($targetDir, $outputPath))->make();
// $zipPath should be: /path/to/another/location/output.zip

$zipPath = (new ZipDirectory($targetDir))->make(true);
// $zipPath should be: /path/to/TargetDir.zip
// And "/path/to/TargetDir" directory should be removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment