The problem that arises here is that $key in the iterator is the full path (since the default flag is RecursiveDirectoryIterator::KEY_AS_PATHNAME ), which includes the relative part specified in the RecursiveDirectoryIterator constructor.
So, for example, we have the following hierarchy:
folderI ├─ folder1 │ ├─ item.php │ └─ so.php └─ folder2 └─ item.html
An iterator created using new RecursiveDirectoryIterator("folderI") .
When you select $key , you will get the following for item.php
folderI/folder1/item.php
Similarly, if we made new RecursiveDirectoryIterator("../somewhere/folderI") , then $key would look like this:
../somewhere/folderI/folder1/item.php
You want to get the file path, not including the path used to create the iterator. Fortunately, RecursiveDirectoryIterator has a method whose sole purpose is to do just that.
RecursiveDirectoryIterator :: getSubPathname ()
You can use the following, which will be easier
$newKey = $iterator->getSubPathname();
This will return the following for item.php , given the same folder structure as shown above:
folder1/item.php
The method can be used as follows:
foreach ($iterator as $key=>$value) { $zip->addFile(realpath($key), $iterator->getSubPathname()) or die ("ERROR: Could not add file: $key"); }
In addition, we can use $iterator->getSubPathname() here because the RecursiveIteratorIterator passes through any unknown method calls to the "internal iterator", which in this case is a recursive DirectoryIterator. Similarly, you can do $iterator->getInnerIterator()->getSubPathname() , both do the same job.