PHP调用循环函数的最优方式及Flysystem解压Zip文件循环问题
我懂你这个痛点——提前拉取的目录列表肯定不会包含后续解压生成的文件,要是Zip里还套着Zip,那更是处理不到对吧?给你两个实用的解决办法:
方案1:分两轮处理(简单直接)
先一次性找出所有Zip文件解压,再重新遍历整个目录处理所有文件(包括刚解压出来的)。这种方式逻辑清晰,适合目录结构不复杂的场景:
// 第一轮:遍历所有文件,先解压全部Zip $contents = $this->manager->listContents('local://my_directory', true); foreach ($contents as $file) { if ($file['extension'] === 'zip') { // 执行解压操作(Flysystem需依赖ziparchive扩展包实现) $extractPath = dirname($file['path']); // 示例:使用ZipArchiveAdapter完成解压 $zipAdapter = new \League\Flysystem\ZipArchive\ZipArchiveAdapter($file['path']); $this->manager->copyFromAdapter($zipAdapter, '', $extractPath); } } // 第二轮:遍历所有文件(含解压产物)进行后续处理 $allContents = $this->manager->listContents('local://my_directory', true); foreach ($allContents as $file) { if ($file['extension'] !== 'zip') { // 跳过已处理的Zip文件 // 这里写你处理非Zip文件的逻辑 } }
方案2:递归实时处理(支持嵌套Zip)
如果需要处理多层嵌套的Zip文件,或者想更高效地实时处理新生成的文件,可以写一个递归函数,处理完一个Zip后立即检查解压目录里的内容:
/** * 递归处理目录及其中的Zip文件 * @param \League\Flysystem\FilesystemManager $manager * @param string $directory */ function processDirectory($manager, $directory) { // 先遍历当前目录的直接子元素,不递归 $contents = $manager->listContents($directory, false); foreach ($contents as $file) { if ($file['type'] === 'dir') { // 递归处理子目录 processDirectory($manager, $file['path']); } elseif ($file['extension'] === 'zip') { // 解压当前Zip到同一目录 $extractPath = dirname($file['path']); $zipAdapter = new \League\Flysystem\ZipArchive\ZipArchiveAdapter($file['path']); $manager->copyFromAdapter($zipAdapter, '', $extractPath); // 解压完成后,立即重新处理当前目录(包含刚解压的文件) processDirectory($manager, $extractPath); // 可选:如果不需要保留原Zip文件,这里可以删除 // $manager->delete($file['path']); } else { // 处理非Zip文件的逻辑 } } } // 启动递归处理 processDirectory($this->manager, 'local://my_directory');
关键注意点
- Flysystem本身没有内置解压方法,必须安装
league/flysystem-ziparchive扩展包才能使用ZipArchiveAdapter - 如果需要避免重复处理同一Zip文件,可以记录已处理的文件路径,或者在解压后直接删除原Zip
- 解压时要注意权限问题,确保目标目录有写入权限
内容的提问来源于stack exchange,提问作者Atnaize
相关产品推荐
相关产品推荐

