make is.dev make it simple. development.
2024年9月10日

PHPでZip圧縮(ZipArchive編)

ZipArchive を使ってZipファイルを作成してみる。

使用環境

・ Amazon Linux 2
・ PHP 8.2.9

事前準備

PHPでZipがサポートされていない場合、ZipArchive が使えない。
エラーが出る場合は、php.ini等でサポートを有効化しておく。
(有効化の仕方は環境によるが、php.iniの末尾や設定ファイルに以下を追記する等)

; Enable zip extension module
extension=zip
/etc/php.d/20-zip.ini

基本サンプル

適当な2ファイルが含まれる新規圧縮ファイルを作成する例。

<?php

// インスタンス生成
$zip = new ZipArchive();

// ZipファイルをOpen
$result = $zip->open( './sample.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE );

if ( $result === true ) {

    // ファイルを追加する
    if ( ! $zip->addFile( './sample.txt', 'sample1.txt' ) ) {
        // error
    }

    // フォルダexの配下にファイルを追加する
    if ( ! $zip->addFile( './sample.txt', 'ex/sample2.txt' ) ) {
        // error
    }

    // Zipを閉じる。この時点で圧縮ファイルが作られる。
    $zip->close();

} else {
    // error
}
PHP
// ZipファイルをOpen
$result = $zip->open( './sample.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE );
PHP

open() の際に、Zipファイルのパス、及び、開く際のモードを指定する。

返り値は成功時はtrueだが、失敗時はエラーコード(数値)が返るので注意が必要。
(結果判定はtrueを明確に判定しないとおかしくなる)

圧縮ファイル生成時に使用するモードは、以下のように組み合わせ(又は第2引数を省略)で指定する。

ZipArchive::CREATEZipファイルがなければ新規作成する。
Zipファイルが既にある場合は、そこにファイルを追加する。
ZipArchive::OVERWRITE既にあるZipファイルを上書く。
(元々あった内容はリセットされる)
ファイルがない場合はエラーを返す。
ZipArchive::CREATE | ZipArchive::OVERWRITEZipファイルがなければ新規作成する。
Zipファイルが既にある場合は上書く。
(元々あった内容はリセットされる)
ZipArchive::CREATE | ZipArchive::EXCLZipファイルがなければ新規作成する。
Zipファイルが既にある場合はとエラーを返す。
(省略)既にあるZipファイルにファイルを追加する。
ファイルがない場合はエラーを返す。
    // ファイルを追加する
    if ( ! $zip->addFile( './sample.txt', 'sample1.txt' ) ) {
        // error
    }

    // フォルダexの配下にファイルを追加する
    if ( ! $zip->addFile( './sample.txt', 'ex/sample2.txt' ) ) {
        // error
    }
PHP

addFile() でファイルを追加する。

第1引数で追加するファイルのパスを指定する。

第2引数で圧縮ファイル内でのパスを指定する。
こちらは未指定も可能だが、第1引数にファイル名だけでなくパスが含まれている場合は圧縮ファイル内で迷子になる。(圧縮はされているが、正しく解凍出来なくなる)
パスはカレントパスの影響も受けるので、第2引数は指定した方が分かりやすく、不具合もおきづらい。

また、第2引数にパスを含める事で、解答時のフォルダ構成を自由に指定出来る。

返り値は成功時にtrue、失敗時はfalseが返るのと併せてWarningが吐かれるので注意。

空のフォルダを追加する

空のフォルダをZipファイルに追加する場合は、addEmptyDir() を使う。

// 空フォルダを追加する
if ( ! $zip->addEmptyDir( 'sample' ) ) {
    // error
}

// 2階層の空フォルダを追加する
if ( ! $zip->addEmptyDir( 'sample2/sample2' ) ) {
    // error
}
PHP

返り値は成功時にtrue、失敗時はfalseが返る。

深い階層のフォルダを追加する場合も、途中段階のフォルダもまとめて追加出来る。

パスワード+暗号化は、、、

setPassword()、setEncryptionName() を使って暗号化することは可能。

<?php

// インスタンス生成
$zip = new ZipArchive();

// ZipファイルをOpen
$result = $zip->open( './sample2.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE );

if ( $result === true ) {

    // パスワードを指定
    $zip->setPassword( 'password' );

    // ファイルを追加して暗号化
    if ( ! $zip->addFile( './sample.txt', 'sample1.txt' ) ) {
        // error
    }
    if ( ! $zip->setEncryptionName( 'sample1.txt', ZipArchive::EM_AES_256 ) ) {
        // error
    }

    // フォルダexの配下にファイルを追加して暗号化
    if ( ! $zip->addFile( './sample.txt', 'ex/sample2.txt' ) ) {
        // error
    }
    if ( ! $zip->setEncryptionName( 'ex/sample2.txt', ZipArchive::EM_AES_256 ) ) {
        // error
    }

    // Zipを閉じる。この時点で圧縮ファイルが作られる。
    $zip->close();

} else {
    // error
}
PHP

ただし、これで作成したZipファイルはWindows標準の機能では解凍出来ない。
作成出来る暗号化アルゴリズムでは現状Windowsに対応しておらず。
(7-Zipなど解凍ソフトを使えば解凍出来るが)

パスワードを設定したい場合は、ZipArchiveではなく別の方法を使った方が良い。
exec() とzipコマンドを使った方法は以下を参照。