PHP / Laravel: ZipArchive
Glossary overview

PHP / Laravel: ZipArchive

ZipArchive — это встроенный в PHP класс, предоставляющий интерфейс для работы с ZIP-архивами: их создания, чтения, извлечения и модификации.
Он входит в расширение php-zip, которое обычно предустановлено (или устанавливается через sudo apt install php-zip).

Что делает ZipArchive

ZipArchive позволяет:

  • 📦 Открывать ZIP-файлы (open()).
  • 📂 Извлекать файлы (extractTo()).
  • Добавлять новые файлы (addFile(), addFromString()).
  • 🗑️ Удалять или переименовывать файлы внутри архива.
  • 🚪 Закрывать архив (close()), чтобы сохранить изменения.

Пример базового использования.

Извлечение архива.

use ZipArchive;

$zip = new ZipArchive();
$path = '/path/to/my-plugin.zip';

if ($zip->open($path) === TRUE) {
    $zip->extractTo('/tmp/my-plugin');
    $zip->close();
    echo "✅ Архив успешно распакован";
} else {
    echo "❌ Ошибка открытия архива";
}

Создание архива.

$zip = new ZipArchive();
$path = '/path/to/new-archive.zip';

if ($zip->open($path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
    $zip->addFile('/path/to/file1.php', 'file1.php');
    $zip->addFile('/path/to/file2.txt', 'docs/file2.txt');
    $zip->close();
    echo "✅ Архив создан";
}

Мой пример: распаковка архива плагина чтобы узнать его версию.

class CreatePlugin extends CreateRecord
{
    protected function afterCreate(): void
    {
        $record = $this->record;
        $path = Storage::disk('local')->path($record->zip_path);
        $zip = new ZipArchive();

        if ($zip->open($path) !== true) {
            Log::error("[PluginVersion] ❌ Cannot open ZIP at {$path}");
            return;
        }

        $tempDir = storage_path('app/private/temp-plugins/temp_plugin_' . uniqid());
        mkdir($tempDir, 0777, true);
        $zip->extractTo($tempDir);
        $zip->close();

        $version = null;
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($tempDir, FilesystemIterator::SKIP_DOTS)
        );

        foreach ($iterator as $file) {
            if ($file->isFile() && str_ends_with($file->getFilename(), '.php')) {
                $contents = @file_get_contents($file->getPathname());

                if (preg_match('/^[\s\/*#@]*Version:\s*([0-9A-Za-z.\-]+)/mi', $contents, $matches)) {
                    $version = trim($matches[1]);
                    Log::info("[PluginVersion] 🏷️ Found version '{$version}' in {$file->getPathname()}");
                    break;
                }
            }
        }

        if ($version) {
            $record->update(['version' => $version]);
            Log::info("[PluginVersion] ✅ Saved version {$version} for plugin ID={$record->id}");
        } else {
            Log::warning("[PluginVersion] ⚠️ No version found for plugin ID={$record->id}");
        }

        $deleteDir = function ($dir) use (&$deleteDir) {
            if (!is_dir($dir)) return;
            foreach (array_diff(scandir($dir), ['.', '..']) as $item) {
                $path = "$dir/$item";
                is_dir($path) ? $deleteDir($path) : unlink($path);
            }
            rmdir($dir);
        };
        $deleteDir($tempDir);
    }
}
Что происходит по шагам:
  1. Открывается архив по пути $path.
  2. Создаётся временная директория $tempDir.
  3. Все файлы распаковываются в неё.
  4. Архив закрывается.

После этого ты можешь рекурсивно пройтись по $tempDir и анализировать содержимое плагина — искать Version:, Plugin Name: и т.д.