Работа с архивами в PHP: от простых до сложных решений

Раздел: Разработка на PHP -> Работа с файлами и данными

Основные подходы к архивации в PHP

Архивация файлов - частая задача при разработке бэкапов, выгрузок данных и автоматизации. В PHP есть несколько способов создания и чтения архивов. Рассмотрим самые распространённые и эффективные решения.

Использование класса ZipArchive (наилучший вариант)

Класс ZipArchive встроен в стандартную библиотеку PHP и подходит для 99% задач. Работает с ZIP-форматом, поддерживает сжатие, пароли, комментарии и многое другое.


$zip = new ZipArchive();
$filename = 'archive.zip';
if ($zip->open($filename, ZipArchive::CREATE) === true) {
    $zip->addFile('file1.txt', 'file1.txt');
    $zip->addFile('file2.jpg', 'images/file2.jpg');
    $zip->close();
    echo 'Архив создан';
} else {
    echo 'Ошибка создания архива';
}

Index php archive (архив в php)

Пояснение: open с флагом CREATE создаёт новый архив. addFile добавляет файл с указанием пути внутри архива. После всех действий вызывается close.

Проблемы: отсутствие расширения zip в PHP выдаёт ошибку. Решение - установка расширения через менеджер пакетов (например, apt install php-zip на Ubuntu). Также при добавлении больших файлов может превыситься лимит памяти - используйте setCompressionIndex с методом сжатия или добавляйте файлы группами.

Как создать архив с помощью системной утилиты zip через exec?

Если расширение zip не установлено, можно вызвать внешнюю программу.


exec('zip -r backup.zip /path/to/folder', $output, $exitCode);
if ($exitCode === 0) {
    echo 'Архив создан успешно';
} else {
    echo 'Ошибка: ' . implode('\n', $output);
}

Пояснение: флаг -r рекурсивно добавляет папку. Важно проверять код возврата. Безопасность: экранируйте пути с escapeshellarg.

Проблема: команда может быть запрещена политикой хостинга. Решение - использовать shell_exec или proc_open с проверкой прав. Также проверьте доступ к исполняемому файлу zip (which zip).

Как создать PHAR-архив?

Класс PharData позволяет создавать архивы в форматах tar, tar.gz, tar.bz2, zip.


$phar = new PharData('archive.tar.gz');
$phar->addFile('file.txt', 'file.txt');
$phar->addFromString('config.php', '<? return [];');
$phar->compress(Phar::GZ);

Пояснение: PharData создаёт tar-архив (без сжатия). compress упаковывает его в tar.gz. Подходит для больших проектов.

Проблема: требуется расширение phar. Часто включено по умолчанию. На старых версиях PHP возможны ошибки с путями - используйте абсолютные пути.

Как создать ZIP-архив без ZipArchive (ручной метод)?

Для демонстрации низкоуровневой работы можно написать собственную функцию, сформировав ZIP-структуру.


function createZipManual($zipPath, $files) {
    $zip = pack('V', 0x04034b50) . pack('v', 10) . pack('v', 0); // сигнатура
    // ... длинный код (упрощён для статьи)
    file_put_contents($zipPath, $zip);
}

Пояснение: такой метод не рекомендуется для продакшена из-за сложности и риска ошибок. Подходит для обучения.

Проблемы: легко ошибиться в смещениях, не обрабатываются большие файлы, медленная работа. Лучше использовать готовые библиотеки.

Углублённые примеры и редкие сценарии

Создание архива с вложенными каталогами (рекурсивный обход)

Пример

$zip = new ZipArchive();
$path = '/var/www/project';
$zip->open('backup_' . date('Ymd') . '.zip', ZipArchive::CREATE);
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($path),
    RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
    if (!$file->isDir()) {
        $localPath = substr($file->getPathname(), strlen($path) + 1);
        $zip->addFile($file->getPathname(), $localPath);
    }
}
$zip->close();

Результат: создан ZIP-архив, содержащий все файлы из папки с сохранением структуры.

Файл: backup_20250215.zip размером 2.3 МБ

Добавление комментария к архиву и настройка сжатия

Пример

$zip = new ZipArchive();
$zip->open('archive.zip', ZipArchive::CREATE);
$zip->setArchiveComment('Бэкап от 15.02.2025');
$zip->addFile('data.log', 'logs/data.log');
for ($i = 0; $i < $zip->numFiles; $i++) {
    $zip->setCompressionIndex($i, ZipArchive::CM_BZIP2);
}
$zip->close();

Пояснение: сжатие BZIP2 даёт лучший коэффициент, но работает медленнее. Комментарий можно прочитать через getArchiveComment.

Установка пароля на ZIP-архив (шифрование)

Пример

$zip = new ZipArchive();
$zip->open('protected.zip', ZipArchive::CREATE);
$zip->setPassword('secret123');
$zip->addFile('private.txt', 'private.txt');
$zip->setEncryptionName('private.txt', ZipArchive::EM_AES_256);
$zip->close();

Примечание: шифрование доступно с PHP 7.2. Без указания метода используется стандартное PKWARE шифрование.

Создание tar-архива с помощью PharData

Пример

$phar = new PharData('backup.tar');
$phar->buildFromDirectory('/var/www/data');
$phar->compress(Phar::GZ); // создаст backup.tar.gz
unlink('backup.tar'); // удалить исходный tar

Результат: единственный файл backup.tar.gz.

backup.tar.gz - 1.1 МБ

Распаковка архива с извлечением только определённых файлов

Пример

$zip = new ZipArchive();
$zip->open('backup.zip');
// Извлечь только файлы с расширением .log
for ($i = 0; $i < $zip->numFiles; $i++) {
    $name = $zip->getNameIndex($i);
    if (pathinfo($name, PATHINFO_EXTENSION) === 'log') {
        $zip->extractTo('/extract/path', $name);
    }
}
$zip->close();

Позволяет избежать извлечения ненужных больших файлов.

Создание самодостаточного PHAR-архива с кодом PHP

Пример

$phar = new Phar('app.phar');
$phar->startBuffering();
$phar->buildFromDirectory(__DIR__ . '/src');
$defaultStub = $phar->createDefaultStub('index.php');
$phar->setStub($defaultStub);
$phar->stopBuffering();

После этого файл app.phar можно запускать как php app.phar.

Обработка ошибок при работе с большими архивами

Пример

ini_set('memory_limit', '512M');
$zip = new ZipArchive();
if ($zip->open('large.zip', ZipArchive::CREATE) !== true) {
    throw new RuntimeException('Не удалось создать архив');
}
// Добавление по одному файлу с проверкой
$files = ['file1.bin', 'file2.bin'];
foreach ($files as $f) {
    if ($zip->addFile($f, basename($f)) === false) {
        error_log('Ошибка добавления: ' . $f);
    }
}
if ($zip->close() === false) {
    error_log('Ошибка закрытия архива');
}

Полезно при обработке тысяч файлов - логируйте каждый сбой.

Архив в PHP - comments

En
Index php archive (php)