Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】PharFileInfo::decompress()メソッドの使い方

decompressメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

decompressメソッドは、Pharアーカイブ内に含まれる圧縮された単一のファイルを解凍するメソッドです。このメソッドはPharFileInfoクラスのインスタンスに対して呼び出され、インスタンスが指し示す特定のファイルを対象とします。具体的には、Pharアーカイブに格納されているzlibまたはbzip2形式で圧縮されたファイルを、そのアーカイブ内で解凍します。ファイルが正常に解凍されると、元の圧縮されたバージョンはアーカイブ内から削除され、解凍済みのファイルに置き換えられます。

このメソッドが成功した場合、真(TRUE)を返します。一方、ファイルがサポートされていない圧縮形式である場合や、対象のPharアーカイブが読み取り専用モードで開かれている場合など、解凍処理に失敗した場合は偽(FALSE)を返します。この機能は、Pharアーカイブから特定のファイルを抽出し、その内容を読み込む前に圧縮を解除する必要がある場合に非常に役立ちます。例えば、アーカイブ内の設定ファイルやリソースファイルが圧縮されている際に、これらをプログラムで利用可能な状態に戻すために使用されます。このメソッドを使用する際は、対象のPharアーカイブが書き込み可能モードで開かれている必要があることに注意してください。

構文(syntax)

1<?php
2
3$isDecompressed = $pharFileInfo->decompress();

引数(parameters)

引数なし

引数はありません

戻り値(return)

bool

指定されたファイルが正常に解凍された場合はtrueを、それ以外の場合はfalseを返します。

サンプルコード

PHP PharFileInfo::decompress でGZIP解凍する

1<?php
2
3/**
4 * PharFileInfo::decompress メソッドの使用例を示します。
5 * Pharアーカイブ内のGZIP圧縮されたファイルを解凍し、その結果を確認します。
6 *
7 * @return bool 処理が成功した場合は true、失敗した場合は false。
8 */
9function demonstratePharDecompressGzip(): bool
10{
11    // 一時的なPharアーカイブと内部ファイルのパスを定義
12    $pharPath = sys_get_temp_dir() . '/my_archive_' . uniqid() . '.phar';
13    $internalFileName = 'my_compressed_content.txt';
14    $originalContent = 'This is a sample content that will be GZIP compressed inside the Phar archive.';
15    $tempSourceFilePath = sys_get_temp_dir() . '/source_file_' . uniqid() . '.txt';
16
17    echo "--- PharFileInfo::decompress デモンストレーション開始 ---\n";
18    echo "Pharアーカイブパス: {$pharPath}\n";
19
20    try {
21        // Pharアーカイブを書き込み可能にする (通常は `php.ini` で `phar.readonly=0` を設定)
22        ini_set('phar.readonly', '0');
23
24        // Pharアーカイブを作成し、GZIP圧縮ファイルを内部に追加
25        $phar = new Phar($pharPath, 0, basename($pharPath));
26        $phar->setStub("<?php __HALT_COMPILER(); ?>"); // 実行可能Pharのためのスタブ
27        $phar->compressFiles(Phar::GZ); // アーカイブ内のファイルをGZIP圧縮で保存する設定
28
29        file_put_contents($tempSourceFilePath, $originalContent);
30        $phar->addFile($tempSourceFilePath, $internalFileName); // ファイルを追加(この時点で圧縮される)
31        unset($phar); // Pharオブジェクトを解放し、変更をディスクに書き込む
32
33        echo "Pharアーカイブ '{$pharPath}' にGZIP圧縮されたファイル '{$internalFileName}' を作成しました。\n";
34
35        // 作成したPharアーカイブを開き、内部ファイルを解凍
36        $phar = new Phar($pharPath);
37        $fileInfo = $phar[$internalFileName];
38
39        // ファイルがGZIP圧縮されていることを確認
40        if (!$fileInfo->isCompressed(Phar::GZ)) {
41            echo "エラー: ファイル '{$internalFileName}' が期待通りGZIP圧縮されていませんでした。\n";
42            return false;
43        }
44        echo "ファイル '{$internalFileName}' はGZIP圧縮されています。\n";
45
46        // PharFileInfo::decompress() を呼び出して圧縮を解除
47        if (!$fileInfo->decompress()) {
48            echo "エラー: ファイル '{$internalFileName}' の圧縮解除に失敗しました。\n";
49            return false;
50        }
51        echo "ファイル '{$internalFileName}' の圧縮を解除しました。\n";
52
53        // 圧縮解除後の状態を確認するため、Pharオブジェクトを再ロード
54        // これにより、ディスク上の変更が確実に反映されます。
55        unset($phar);
56        $phar = new Phar($pharPath);
57        $fileInfo = $phar[$internalFileName];
58
59        // 解除後のファイルが非圧縮状態になっていることを確認
60        if ($fileInfo->isCompressed()) {
61            echo "エラー: 圧縮解除後もファイル '{$internalFileName}' が圧縮されています。\n";
62            return false;
63        }
64        echo "ファイル '{$internalFileName}' は非圧縮状態になりました。\n";
65
66        // 解凍されたファイルのコンテンツを読み込み、オリジナルと比較
67        $readContent = file_get_contents('phar://' . $pharPath . '/' . $internalFileName);
68        echo "解凍後のファイル内容: '{$readContent}'\n";
69
70        if ($readContent === $originalContent) {
71            echo "結果: コンテンツの整合性確認に成功しました。\n";
72            return true;
73        } else {
74            echo "エラー: コンテンツの整合性確認に失敗しました。期待値と異なります。\n";
75            return false;
76        }
77
78    } catch (Exception $e) {
79        echo "エラーが発生しました: " . $e->getMessage() . "\n";
80        return false;
81    } finally {
82        // 後処理: 一時ファイルをクリーンアップ
83        if (file_exists($tempSourceFilePath)) {
84            unlink($tempSourceFilePath);
85        }
86        if (file_exists($pharPath)) {
87            unlink($pharPath);
88            echo "Pharアーカイブ '{$pharPath}' を削除しました。\n";
89        }
90        echo "--- デモンストレーション終了 ---\n";
91    }
92}
93
94// デモンストレーション関数を実行
95if (demonstratePharDecompressGzip()) {
96    echo "\nデモンストレーションは正常に完了しました。\n";
97} else {
98    echo "\nデモンストレーションは失敗しました。\n";
99}

PHP 8のPharFileInfo::decompressメソッドは、PHPのPhar(PHP Archive)形式のアーカイブ内に含まれる、個別のファイルの圧縮を解除するために使用されます。このメソッドは、特にGZIP圧縮されたファイルを元の非圧縮状態に戻す際に役立ちます。

このメソッドは、Pharアーカイブ内の特定のファイル情報を表すPharFileInfoオブジェクトに対して、引数なしで呼び出します。圧縮解除処理が成功した場合はtrueを返し、何らかの理由で失敗した場合はfalseを返します。

サンプルコードでは、まず一時的なPharアーカイブを作成し、GZIP圧縮されたファイルをその内部に追加しています。その後、PharFileInfo::decompress()メソッドを呼び出して、追加したファイルの圧縮を解除します。最終的に、圧縮解除後のファイルが非圧縮状態になっていることと、その内容が元のデータと一致することを検証し、メソッドが正常に機能することを示しています。この機能により、Pharアーカイブ内のコンテンツを柔軟に管理し、必要に応じて元の形式に戻すことが可能です。

PharFileInfo::decompressメソッドを使用する際は、まずphp.iniphar.readonly=0が設定されているか、スクリプト内で一時的にini_setで書き込みを許可しているかを確認してください。Pharアーカイブ内のファイルを変更するには、書き込み権限が必要です。このメソッドは解凍の成否をブール値で返すため、必ず戻り値を確認し、失敗時には適切なエラー処理を行うことが重要です。ファイルを解凍した後、Pharオブジェクトの内部状態を確実に更新するには、一度オブジェクトを解放し、Pharアーカイブを再度読み込み直す必要がある場合があります。また、一時的なPharファイルや圧縮元ファイルを使用する場合は、不要なファイルを残さないよう、必ず処理の最後に適切にクリーンアップしてください。

PharFileInfo::decompress() でファイルを解凍する

1<?php
2
3/**
4 * Demonstrates how to use PharFileInfo::decompress() to decompress a file
5 * stored within a PHP Archive (Phar).
6 *
7 * This example creates a temporary Phar archive, adds a compressed file to it,
8 * then opens the archive and decompresses that specific file using
9 * PharFileInfo::decompress().
10 *
11 * Note: The 'zip' keyword in the prompt refers to common compression
12 * algorithms. Phar archives can use Zlib (related to ZIP's DEFLATE)
13 * or Bzip2 compression. This example uses Gzip compression, which is
14 * based on the Zlib library. PharFileInfo::decompress() operates on
15 * files *inside* a Phar, not on external .zip files.
16 */
17function demonstratePharFileDecompression(): void
18{
19    // Define temporary paths for the demo
20    $tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'phar_decompress_demo_' . uniqid();
21    $pharPath = $tempDir . DIRECTORY_SEPARATOR . 'my_archive.phar';
22    $originalFilePath = $tempDir . DIRECTORY_SEPARATOR . 'data.txt';
23    $internalFileName = 'example_data.txt';
24
25    // 1. Setup: Create a temporary directory and an original file
26    if (!mkdir($tempDir) && !is_dir($tempDir)) {
27        echo "Error: Could not create temporary directory: $tempDir\n";
28        return;
29    }
30    file_put_contents($originalFilePath, "This is some sample text content to be compressed and decompressed.");
31    echo "Created original file: " . realpath($originalFilePath) . "\n\n";
32
33    try {
34        // Ensure Phar can be written to (php.ini setting phar.readonly must be 'Off')
35        if (ini_get('phar.readonly') === '1') {
36            echo "Warning: 'phar.readonly' is 'On'. Attempting to set it to 'Off' for this script.\n";
37            // Attempt to change the setting; this might fail depending on PHP configuration.
38            ini_set('phar.readonly', '0');
39            if (ini_get('phar.readonly') === '1') {
40                echo "Error: Failed to set 'phar.readonly' to 'Off'. Cannot create Phar archive.\n";
41                // Clean up temporary files before exiting
42                throw new Exception("Phar creation blocked by 'phar.readonly' setting.");
43            }
44            echo "Successfully set 'phar.readonly' to 'Off'.\n";
45        }
46
47        // 2. Create a new Phar archive and add a compressed file
48        echo "Creating Phar archive: $pharPath\n";
49        $phar = new Phar($pharPath);
50        $phar->startBuffering(); // Start buffering changes
51
52        // Add the original file to the Phar with a new internal name
53        $phar->addFile($originalFilePath, $internalFileName);
54
55        // Get the PharFileInfo object for the added file
56        $fileInPhar = $phar[$internalFileName];
57
58        // Compress the file *within* the Phar using Gzip compression
59        // This makes the file compressed, so decompress() has something to do.
60        if ($fileInPhar->compress(Phar::GZ)) {
61            echo "File '$internalFileName' added to Phar and compressed with GZ.\n";
62        } else {
63            echo "Warning: Could not compress file '$internalFileName' within Phar.\n";
64        }
65
66        $phar->stopBuffering(); // Stop buffering and save changes
67        unset($phar); // Close the Phar handle to ensure it's saved to disk
68
69        echo "Phar archive created successfully.\n\n";
70
71        // 3. Open the existing Phar archive and decompress the file
72        echo "Opening Phar archive to decompress an internal file...\n";
73        $phar = new Phar($pharPath);
74
75        if (isset($phar[$internalFileName])) {
76            $fileInfoToDecompress = $phar[$internalFileName]; // Get PharFileInfo object
77
78            echo "Current compression status of '$internalFileName': " . ($fileInfoToDecompress->isCompressed() ? 'Compressed' : 'Not Compressed') . "\n";
79
80            if ($fileInfoToDecompress->isCompressed()) {
81                echo "Attempting to decompress '$internalFileName'...\n";
82                // Call the decompress() method
83                $success = $fileInfoToDecompress->decompress();
84
85                if ($success) {
86                    echo "Successfully decompressed '$internalFileName' within the Phar.\n";
87                    echo "New compression status of '$internalFileName': " . ($fileInfoToDecompress->isCompressed() ? 'Compressed' : 'Not Compressed') . "\n";
88                    // Verify decompression by checking its status
89                    if (!$fileInfoToDecompress->isCompressed()) {
90                        echo "Verification: The file is no longer marked as compressed.\n";
91                    } else {
92                        echo "Verification: The file is still marked as compressed, which is unexpected after decompress().\n";
93                    }
94                } else {
95                    echo "Failed to decompress '$internalFileName'.\n";
96                }
97            } else {
98                echo "File '$internalFileName' is not compressed. No decompression operation was performed.\n";
99            }
100        } else {
101            echo "Error: File '$internalFileName' not found in the Phar archive.\n";
102        }
103
104    } catch (PharException $e) {
105        echo "Phar Error: " . $e->getMessage() . "\n";
106    } catch (Exception $e) {
107        echo "General Error: " . $e->getMessage() . "\n";
108    } finally {
109        // 4. Clean up temporary files and directory
110        echo "\nCleaning up temporary files...\n";
111        if (file_exists($pharPath)) {
112            try {
113                // Phar::unlinkSelf() is the recommended way to delete a Phar archive
114                // as it ensures all file handles are properly closed.
115                $pharCleaner = new Phar($pharPath);
116                $pharCleaner->unlinkSelf();
117                echo "Removed Phar archive: $pharPath\n";
118            } catch (PharException $e) {
119                echo "Warning: Could not unlink Phar archive using unlinkSelf(). Attempting direct unlink.\n";
120                if (file_exists($pharPath) && !unlink($pharPath)) {
121                    echo "Warning: Could not delete Phar archive directly: $pharPath\n";
122                }
123            }
124        }
125        if (file_exists($originalFilePath)) {
126            unlink($originalFilePath);
127        }
128        if (is_dir($tempDir)) {
129            rmdir($tempDir);
130        }
131        echo "Cleanup complete.\n";
132    }
133}
134
135// Execute the demonstration function
136demonstratePharFileDecompression();

PharFileInfo::decompress()は、PHPのPhar(PHP Archive)拡張機能に属するメソッドで、Pharアーカイブ内に含まれる特定の圧縮ファイルを解凍し、元の非圧縮状態に戻すために使用されます。Pharは複数のファイルを一つにまとめることができ、その際、ファイルごとにGzipやBzip2といった形式で圧縮しておくことが可能です。

このメソッドは引数を必要とせず、呼び出すだけで対象のPharファイル情報オブジェクトが指すファイルが解凍されます。処理が成功した場合にはtrue、失敗した場合にはfalseという真偽値(bool)を戻り値として返します。システムエンジニアを目指す方にとって、「zip」というキーワードは一般的な外部ZIPファイルを思い起こさせるかもしれませんが、このdecompressメソッドは、あくまでPharアーカイブ「内部」のファイルが圧縮されている場合に、その圧縮を解除する機能を提供します。外部のZIPファイルそのものを直接扱うものではありませんのでご注意ください。

サンプルコードでは、一時的なPharアーカイブを作成し、内部のテキストファイルをGzip形式で圧縮した後、その圧縮されたPharFileInfoオブジェクトに対してdecompress()を呼び出して解凍しています。これにより、アーカイブ内のファイルの圧縮状態を管理できます。Pharアーカイブの書き込みや変更を行う際には、PHPの実行設定であるphar.readonlyOffになっている必要がありますので、スクリプト実行前に確認することが重要です。

PharFileInfo::decompress()は、PHPアーカイブ(Phar)内部のファイルを解凍するメソッドです。外部の.zipファイルを直接解凍する機能ではないため、キーワードの「zip」に惑わされないようご注意ください。このメソッドが正しく動作するには、対象ファイルがPhar::GZなどで事前に圧縮されている必要があります。圧縮されていないファイルには効果がありません。Pharアーカイブの作成や変更には、php.iniphar.readonly設定がOffである必要があります。本番環境では通常Onのため、この点を考慮し、開発時や一時的な利用に留めることが安全です。処理の成否は戻り値のboolで確認し、エラーハンドリングと一時ファイルの確実なクリーンアップを忘れずに行ってください。

関連コンテンツ