$certificates */ public function create(Collection $certificates, ?string $password = null): string { $archivePath = tempnam(sys_get_temp_dir(), 'certs_').'.zip'; $zip = new ZipArchive; if ($zip->open($archivePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { throw new RuntimeException('Unable to create ZIP archive.'); } if ($password !== null) { $zip->setPassword($password); } $usedNames = []; foreach ($certificates as $certificate) { if (blank($certificate->file_path) || ! Storage::disk('local')->exists($certificate->file_path)) { continue; } $entryName = $this->uniqueEntryName($certificate, $usedNames); $usedNames[] = $entryName; $zip->addFromString($entryName, Storage::disk('local')->get($certificate->file_path)); if ($password !== null) { $zip->setEncryptionName($entryName, ZipArchive::EM_AES_256); } } if ($zip->count() === 0) { $zip->close(); @unlink($archivePath); throw new RuntimeException('No files were available to add to the archive.'); } $zip->close(); return $archivePath; } /** * @param array $usedNames */ private function uniqueEntryName(Certificate $certificate, array $usedNames): string { $extension = pathinfo($certificate->file_path, PATHINFO_EXTENSION); $base = Str::slug($certificate->title) ?: 'certificate'; $name = $base.'.'.$extension; $counter = 1; while (in_array($name, $usedNames, true)) { $name = $base.'-'.(++$counter).'.'.$extension; } return $name; } }