Archiving a Directory

Recursively tracing out a full directory and saving the files in an archive seemed like a fairly easy thing to do. After all, I knew how to glob() and was reasonably sure that the environment I was working in had the ZIP extension built into the PHP. But wait... Recursion? glob() does not handle recursion easily.

After digging around a little bit through some Stack Overflow articles I bumped into an alternate method to glob()… A handy set of SPL classes. After all, PHP 5 and cool new features and stuff. A bit of experimentation and I ended up with this little script that creates a friendly iterator-able recursive set of files that has a delightfully small memory footprint.

  1. $directoryIterator = new RecursiveDirectoryIterator($directory_path);

  2. $iteratorIterator = new RecursiveIteratorIterator($directoryIterator);

  3. foreach ($iteratorIterator as $file)

  4. {

  5. // do something

  6. }

RecursiveDirectoryIterator creates an interface to view the contents of a directory and RecursiveIteratorIterator (I love that name) can loop through iterators. It's nice, simple, and each $file in the foreach() is a full SplFileInfo object. Which opens up a lot of handy functionality.

Once I had this down it was a piece of cake to implement the ZipArchive logic. Once you create that class and open up a file, you can add files, one at a time, to the archive. Which was perfect, given that RecursiveIteratorIterator was looping through the files one at a time.

  1. $directoryIterator = new RecursiveDirectoryIterator($directory_path);

  2. $iteratorIterator = new RecursiveIteratorIterator($directoryIterator);

  3. $archive = new ZipArchive();

  4. $archive->open($archive_path, ZipArchive::OVERWRITE);

  5. foreach ($iteratorIterator as $file)

  6. {

  7. $archive->addFile(

  8. $file->getPathname(),

  9. str_replace($directory_path, '', $file->getPathname())

  10. );

  11. }

  12. $archive->close();

One area that got a little hairy was with the ZipArchive errors. If the archive is unable to open (file permissions, existing file, etc) ZipArchive::open() can return any one of a wide range of interger statuses to show the failure. Mapping out what problem showed up is a little messy. Also, ZipArchive::addFile() only returns a boolean if it worked with no hint as to the problem. Inconsistency in PHP is just par for course, though, even for some of the newer features.

A built out repository (archiver) of this script is available on my GitHub account, complete with some error checking and commented parameter areas. This was a fun venture into an area of PHP that I haven't had a ton of experience in (SPL) and I hope to find an excuse to jump in again soon!