The
PHP Zip archive extension is used to manage Zip archives and the files they contain. To use this extension in PHP 5, all you need to do is enable the
php_zip.dll inside of the
php.ini file. In this article, I explain how to manage Zip archive files in PHP using a number of demo PHP applications. Specifically, you'll learn how to:
- create Zip archives.
- add files and folders inside the archive from a string and from a given path.
- delete and rename files using their indexes and names.
- list the ZipArchive object details (number of files, filenames, comments, statusSys, etc.).
Creating Zip Archives in PHP and Adding Files Inside Them
To create a Zip archive in PHP you can use the predefined constant ZIPARCHIVE::CREATE; the archive will be created if it does not exist. (To add files inside an archive you can use the addFile and addFromString methods described later.) The first demo application (add_file_from_string.php) creates (if it doesn't exist) or opens the archive1.zip Zip archive and then adds a file to a Zip archive using the addFromString() method, which has the following prototype:
bool ZipArchive::addFromString ( string $localname , string $contents ): Add a file to a Zip archive using its contents.
Here is the code for add_file_from_string.php:
<?php
//Create the ZipArchive object
$zip = new ZipArchive;
//Open/Create if not exist the archive1 zip archive
if ($zip->open("archive1.zip", ZIPARCHIVE::CREATE)!==TRUE) {
exit("cannot open <$filename>"."<br />");
}
//Add a file to a Zip archive using its contents
$zip->addFromString('test1.txt', 'Creating an Zip archive by adding a file to a Zip archive using its contents!');
//Close the active archive
$zip->close();
echo 'The test1.txt file text was successfully added to the archive1.zip';
?>
Here is the output of
add_file_from_string.php and you can also see it in
Figure 1:
The test1.txt file text was successfully added to the archive1.zip
Click here for larger image
Figure 1. The archive1.zip Content: The test1.txt File
The second demo application (add_file_directory.php) also uses the archive1.zip archive to print all the ZipArchive object details (such as status, statusSys, numFiles, filename, comment, or a specified argument, in this case the archive comment and number of files) to add an empty directory named Subdirectory1. This application uses the archive1.zip archive to add a new file as well using the addFile method. Below are the addFile() and addEmptyDir() methods prototypes:
bool ZipArchive::addFile ( string $filename [, string $localname ] ) : adds a file to a Zip archive from a given path
bool ZipArchive::addEmptyDir ( string $dirname ) : adds an empty directory in the archive.
Here is the code for add_file_directory.php:
<?php
$zip = new ZipArchive();
$zip->open('archive1.zip');
//List all the ZipArchive object details
print_r($zip);
//Adding an empty directory
if($zip->addEmptyDir('Subdirectory1')) {
echo 'Create a new directory'. "<br />";
} else {
echo 'Could not create the directory'. "<br />";
}
//Adding a new text file, the test2.txt
$zip->addFile('test2.txt');
//List the archive1.php comment
echo "Comment: " . $zip->comment . "<br />";
//List the archive1.php number of files
echo "numFile:" . $zip->numFiles . "<br />";
?>
Here is the output of the
add_file_directory.php listing and you can also see it in
Figure 2:
ZipArchive Object ( [status] => 0 [statusSys] => 0 [numFiles] => 2 [filename] => D:\Apache Group\Apache2\htdocs\php\ZIP\archive1.zip [comment] => PHP ZIP ARCHIVE ) Create a new directory
Comment: PHP ZIP ARCHIVE
numFile:4
Click here for larger image
Figure 2. The archive2.zip Object Details
The next demo application creates the archive2.zip Zip archive, which contains two files: test3.txt and test4.txt. (You will see how to use this application later in the article.) Here is the code for archive2.php:
<?php
//Create the ZipArchive object
$zip = new ZipArchive;
//Open/Create if not exist the archive1 zip archive
if ($zip->open("archive2.zip", ZIPARCHIVE::CREATE)!==TRUE) {
exit("cannot open <$filename>\n");
}
//Adds a file to a Zip archive from the given path
$zip->addFile('test3.txt');
//Add a file to a Zip archive using its contents
$zip->addFromString('test4.txt', 'Creating an Zip archive by adding a file to a Zip archive using its contents!');
//Close the active archive
$zip->close();
echo 'The test3.txt file text was successfully added to the archive2.zip';
?>
Here is the output of
archive2.php and you can also see it in
Figure 3:
The test3.txt file text was successfully added to the archive2.zip using the addFile method
The test4.txt file text was successfully added to the archive2.zip using the addFromString method.
Click here for larger image
Figure 3. The archive2.zip Content
Extracting a Zip Archive in PHP
The demo application in this section (
extract_archives.php) shows you how to extract the archive contents into a specified folder, using the
extractTo() method:
bool ZipArchive::extractTo ( string $destination [, mixed $entries ] ) : extract the archive contents. The
archive1.zip and the
archive2.zip archives will be extracted to the
archive folder, as you can see in the
Figure 4.
Here is the code for extract_archives.php:
<?php
$zip1 = new ZipArchive;
$zip2 = new ZipArchive;
//Opens a Zip archive
$extract1 = $zip1->open('archive1.zip');
$extract2 = $zip2->open('archive2.zip');
if (($extract1 === TRUE)&&($extract2 === TRUE)) {
//Extract the archive contents
$zip1->extractTo('archive');
$zip2->extractTo('archive');
//Close a Zip archive
$zip1->close();
$zip2->close();
echo 'The archive1.zip and archive2.zip were extracted in the archive folder!';
} else {
echo 'The extraction of the archive1.zip and archive2.zip failed!';
}
?>
The output of the extract_archives.php:
The archive1.zip and archive2.zip were extracted in the archive folder!
Click here for larger image
Figure 4. The Contents of the Archive Folder, Obtained After archive1 and archive2 Were Extracted
The next demo application (extract_to_specified_folder.php) extracts the Zip archive content into a specified folder using the extractTo() method described above. Here is the code for extract_to_specified_folder.php:
<?php
//Create the object
$zip = new ZipArchive();
// open archive
if ($zip->open('archive1.zip') !== TRUE) {
die ("Could not open archive");
}
// extract contents to destination directory
$zip->extractTo('../ZIP_extract/');
//Close the archive
$zip->close();
echo "Archive extracted to ZIP_extract folder!";
?>
Here is the output of the
extract_to_specified_folder.php and you can also see it in
Figure 5:
Archive extracted to ZIP_extract folder!
Click here for larger image
Figure 5. The ZIP_extract Folder Containing the archive1 Files
The following demo application (filelist.php) extracts from archive2 a file list array containing two files: test3.txt and test4.txt and puts them into the ZIP_TEST folder. Here is the code for filelist.php:
<?php
//Create object
$zip = new ZipArchive();
//Open archive
if ($zip->open('archive2.zip') !== TRUE) {
die ("Could not open archive");
}
//Extract the selected files into the ZIP_TEST destination directory
$fileList = array('test3.txt','test4.txt');
$zip->extractTo('../ZIP_TEST/', $fileList);
//Close archive
$zip->close();
echo "The test3.txt and test4.txt files from the archive2.zip archive extracted successfully to the specified directory!";
?>
Here is the output of the
filelist.php listing and you can also see it in
Figure 6:
The test3.txt and test4.txt files from the archive2.zip archive extracted successfully to the specified directory!
Click here for larger image
Figure 6. The Selected Files Extracted from the archive2 into the ZIP_TEST Destination Directory Getting the Details of an Entry Defined by Its Index
To get the details of a specific file you can use the statIndex method:
mixed ZipArchive::statIndex ( int $index [, int $flags ] ).
The next demo application (statIndex.php) iterates over the file list in archive2.zip and prints all the details for each one of the entries. Here is the code for statIndex.php:
<?php
//Create object
$zip = new ZipArchive();
//Open the archive2.zip
if ($zip->open('archive2.zip') !== TRUE) {
die ("Could not open archive");
}
//Get the number of files in archive2.zip
$numFiles = $zip->numFiles;
//Iterate over the file list
for ($i=0; $i<$numFiles; $i++) {
//Get the details of an entry defined by its index
print_r($zip->statIndex($i));
print "<br />";
}
// close archive
$zip->close();
?>
The output of the 5.php listing is:
Array ( [name] => test3.txt [index] => 0 [crc] => -1117485446 [size] => 45 [mtime] => 1269720238 [comp_size] => 46 [comp_method] => 8 )
Array ( [name] => test4.txt [index] => 1 [crc] => -1780851877 [size] => 77 [mtime] => 1269786772 [comp_size] => 62 [comp_method] => 8 )
The next demo application (locate.php) also gets the details of a file, if the archive1.zip contains that file. The locateName method returns the index of the file in the archive and uses the predefined constant ZIPARCHIVE::FL_NODIR, which ignores the directory component. Here is the ZIPARCHIVE::FL_NODIR constant's prototype:
mixed ZipArchive::locateName ( string $name [, int $flags ] )
Here is the code for locate.php:
<?php
//Create object
$zip = new ZipArchive();
//Open archive
if ($zip->open('archive1.zip') === TRUE) {
//Find a specify file in archive and print its details
$locate_file = $zip->locateName('test2.txt', ZIPARCHIVE::FL_NODIR);
if ($locate_file == TRUE) {
$file = $zip->statIndex($locate_file);
print_r($file);
}
// close archive
$zip->close();
}
?>
The output of the locate.php listing is:
Array ( [name] => test2.txt [index] => 2 [crc] => -513033757 [size] => 50 [mtime] => 1269715222 [comp_size] => 49 [comp_method] => 8 )
Delete and Rename Files from Zip Archives in PHP
To delete or rename Zip archives in PHP you can use the name or the index. The methods that take care of that are:
bool ZipArchive::deleteIndex ( int $index ) -- Deletes an entry in the archive using its index
bool ZipArchive::deleteName ( string $name ) -- Deletes an entry in the archive using its name
bool ZipArchive::renameIndex ( int $index , string $newname ) -- Renames an entry defined by its index
bool ZipArchive::renameName ( string $name , string $newname ) -- Renames an entry defined by its name
The next demo application (rename.php) uses all the above methods to rename the file with the "index=3" as "renameByIndex.txt" and the "test4.txt" as "renameByName.txt". Here is the code for rename.php:
<?PHP
// create object
$zip = new ZipArchive();
// open archive
if ($zip->open('archive2.zip') !== TRUE) {
die ("Could not open archive");
}
// rename file in archive using index
$zip->renameIndex(0, 'renamedByIndex.txt') or die("ERROR: Could not rename file");
// rename file in archive using name
$zip->renameName("test3.txt", "renamedByName.txt") or die("ERROR: Could not rename file");
// close and save archive
$zip->close();
echo "The files were successfully renamed in the archive2.zip archive!";
?>
Here is the output of the
rename.php listing and you can also see it in
Figure 7 and
Figure 8:
The files were successfully renamed in the archive2.zip archive!
Click here for larger image
Figure 7. The Initial Content of archive2.zip
Click here for larger image
Figure 8. The Contents of archive2.zip after the Files Were Renamed
The next application (delete.php) deletes from archive2.zip the file with the "index=1" and the renameByIndex.txt text file using the deleteIndex() and deleteName() methods. Here is the code for delete.php:
<?PHP
// create object
$zip = new ZipArchive();
// open archive
if ($zip->open('archive2.zip') !== TRUE) {
die ("Could not open archive");
}
//Delete the file with the index=1 from the archive2.zip
$zip->deleteIndex(0) or die("ERROR: Could not delete file with the index=1 ");
//Delete the test3.txt file from archive2.zip
$zip->deleteName('renameByIndex.txt') or die("ERROR: Could not delete the test3.txt file ");
echo "The files were successfully deleted from the archive2.zip archive!";
// close and save archive
$zip->close();
?>
Because the archive contained only two files and both were deleted, the archive2.zip was deleted too.
The next application (add_text_files.php) iterates over the archive files and adds all .txt files from the current directory to text_archive.zip. Here is the code for add_text_files.php:
<?php
//Create the object
$zip = new ZipArchive();
//Open the archive
if ($zip->open('text_archive.zip', ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
//Adding all .txt files from the current directory to text_archive.zip
foreach (glob ('*.txt') as $textfile) {
$zip->addFile($textfile);
}
//Close the archive
$zip->close();
echo "text_archive.zip was created successfully!";
?>
Here is the output of the add_text_files.php listing:
text_archive.zip was created successfully!
Click here for larger image
Figure 9. Grouping All the Text Files from the Current Directory into a New Archive, text_archive.zip
Conclusion
Working with the PHP Zip archive extension is very simple and even fun, as you have seen in all the applications in this article. All you have to do is handle the extension methods and you will successfully manage all the possible Zip archive operations.
Code Download
About the Author
Octavia Andreea Anghel is a senior PHP developer currently working as a primary trainer for programming teams that participate at national and international software-development contests. She consults on developing educational projects at a national level. She is a coauthor of the book "XML Technologies -- XML in Java" (Albastra, ISBN 978-973-650-210-1), for which she wrote the XML portions. In addition to PHP and XML, she's interested in software architecture, web services, UML, and high-performance unit tests. to e-mail her.