【PHP8.x】Phar::decompressFiles()メソッドの使い方
decompressFilesメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
decompressFilesメソッドは、Pharアーカイブ内に含まれるファイルの圧縮を解除するメソッドです。Pharは、PHPアプリケーションやライブラリを構成する複数のファイルを、一つのアーカイブファイルとしてまとめるための特殊な形式です。このdecompressFilesメソッドは、そのPharアーカイブの中に格納されている個々のファイルがGzipまたはBzip2といった形式で圧縮されている場合に、それらをオリジナルの未圧縮状態に戻す処理を実行します。
このメソッドが特に重要なのは、Pharアーカイブ 自体 の圧縮状態を変更するのではなく、アーカイブ 内 の個々のファイルのみに作用する点です。これにより、Pharファイル全体のサイズは維持しつつも、内部のファイルを読み込む際のパフォーマンスを向上させたり、特定の処理で未圧縮データが必要な場合に柔軟に対応したりすることが可能になります。
この機能を正しく利用するためには、PHPの設定オプションであるphar.readonlyが0(書き込み可能)に設定されている必要があります。メソッドの実行により、Pharアーカイブ内の圧縮されたファイルは一括で未圧縮の状態に変換され、その操作の成否はブール値で返されます。このメソッドは、Pharアーカイブ内のコンテンツを効率的に管理するために利用されます。
構文(syntax)
1<?php 2$phar = new Phar('path/to/archive.phar'); 3$phar->decompressFiles(); 4?>
引数(parameters)
array $files, ?string $extension = null
- array $files: 圧縮解除するファイルパスの配列
- ?string $extension = null: 圧縮解除する際に使用する圧縮形式を指定します。指定しない場合は、Phar::detectDependencies()によって自動的に検出されます。
戻り値(return)
bool
Phar::decompressFilesメソッドは、pharアーカイブ内のファイルを解凍する処理の成否を真偽値(bool)で返します。成功した場合は true を、失敗した場合は false を返します。
サンプルコード
PHP Phar::decompressFiles で圧縮ファイルを解凍する
1<?php 2 3/** 4 * Pharアーカイブ内の特定の圧縮ファイルを解凍するサンプル関数。 5 * 6 * この関数は、システムエンジニアを目指す初心者向けに、Phar::decompressFiles() メソッドの 7 * 使用方法を簡潔かつ具体的に示します。 8 * 9 * 以下の手順を実行します: 10 * 1. 一時ディレクトリとテストファイルを作成します。 11 * 2. 新しいPharアーカイブを作成し、これらのテストファイルをGzip圧縮形式で追加します。 12 * 3. 作成したPharアーカイブ内の特定のファイルを解凍します。 13 * 4. 解凍処理の結果を表示し、ファイルの状態を確認します。 14 * 5. 作成したPharアーカイブおよび一時ファイルをクリーンアップします。 15 */ 16function demonstratePharDecompressFiles(): void 17{ 18 // Pharアーカイブの作成と変更には、phar.readonly を '0' に設定する必要があります。 19 // この設定はスクリプトの実行期間中のみ有効で、スクリプト終了後に元に戻ります。 20 $oldReadonly = ini_get('phar.readonly'); 21 ini_set('phar.readonly', '0'); 22 23 $pharPath = __DIR__ . '/my_sample_archive.phar'; 24 $tempDir = __DIR__ . '/temp_for_phar_decompress/'; 25 $testFile1Path = $tempDir . 'document1.txt'; 26 $testFile2Path = $tempDir . 'report.txt'; 27 $testFile3Path = $tempDir . 'data/config.json'; // サブディレクトリ内のファイル 28 29 // 既存のPharアーカイブが存在する場合は、このスクリプトの実行前に削除します。 30 if (file_exists($pharPath)) { 31 unlink($pharPath); 32 } 33 34 try { 35 echo "--- Phar::decompressFiles() サンプル開始 ---\n\n"; 36 37 // 1. テスト用のファイルとディレクトリを準備する 38 // Pharアーカイブに含める元のファイルを作成します。 39 if (!is_dir($tempDir)) { 40 mkdir($tempDir, 0777, true); 41 } 42 if (!is_dir($tempDir . 'data/')) { 43 mkdir($tempDir . 'data/', 0777, true); 44 } 45 46 file_put_contents($testFile1Path, "これはドキュメント1の重要な内容です。\nバージョンA."); 47 file_put_contents($testFile2Path, "年次レポートのデータ。\n最終更新日: " . date('Y-m-d')); 48 file_put_contents($testFile3Path, '{"api_key": "abc123", "version": "1.0"}'); 49 50 echo "1. テストファイルを作成しました:\n"; 51 echo " - " . basename($testFile1Path) . "\n"; 52 echo " - " . basename($testFile2Path) . "\n"; 53 echo " - " . basename($testFile3Path) . "\n\n"; 54 55 // 2. 新しいPharアーカイブを作成し、ファイルを圧縮して追加する 56 // Pharアーカイブ内にファイルを保存する際、Phar::GZ を指定してGzip圧縮します。 57 $phar = new Phar($pharPath); 58 $phar->startBuffering(); // アーカイブへの書き込みを効率化するためにバッファリングを開始 59 60 // Pharアーカイブ内でのパスを指定してファイルを追加 61 $phar->addFile($testFile1Path, 'docs/document1.txt', Phar::GZ); 62 $phar->addFile($testFile2Path, 'reports/report.txt', Phar::GZ); 63 $phar->addFile($testFile3Path, 'configs/data/config.json', Phar::GZ); 64 65 // stub はPharアーカイブがPHPスクリプトとして実行されたときの起動コードです。 66 // ここでは簡単なデフォルトのstubを設定します。 67 $phar->setStub($phar->createDefaultStub('index.php')); 68 69 $phar->stopBuffering(); // バッファリングを終了し、変更をディスクに書き込む 70 echo "2. Pharアーカイブ '" . basename($pharPath) . "' を作成し、ファイルを圧縮して追加しました。\n\n"; 71 72 // Pharアーカイブ内のファイルリストと圧縮状態を確認 73 echo "Pharアーカイブ内の初期ファイルリスト (圧縮状態):\n"; 74 foreach (new RecursiveIteratorIterator($phar) as $file) { 75 /** @var PharFileInfo $file */ 76 echo " - " . $file->getPathname(); 77 echo " (圧縮状態: " . ($file->isCompressed(Phar::GZ) ? 'GZ圧縮済み' : '未圧縮') . ")\n"; 78 } 79 echo "\n"; 80 81 // 3. Pharアーカイブから特定のファイルを解凍する 82 // 解凍したいファイルのPharアーカイブ内でのパスを配列で指定します。 83 // ここでは 'document1.txt' と 'config.json' を解凍します。 84 $filesToDecompress = [ 85 'docs/document1.txt', 86 'configs/data/config.json' 87 ]; 88 89 echo "3. 以下のファイルをPharアーカイブ内で解凍しています: " . implode(', ', $filesToDecompress) . "\n"; 90 $success = $phar->decompressFiles($filesToDecompress); 91 92 if ($success) { 93 echo " ファイルの解凍に成功しました。\n\n"; 94 95 // 解凍後のファイルの状態を確認 96 echo "解凍後のPharアーカイブ内のファイルリスト (新しい圧縮状態):\n"; 97 foreach (new RecursiveIteratorIterator($phar) as $file) { 98 /** @var PharFileInfo $file */ 99 echo " - " . $file->getPathname(); 100 // isCompressed() で圧縮状態を再確認。指定したファイルは '未圧縮' になっているはず。 101 echo " (圧縮状態: " . ($file->isCompressed(Phar::GZ) ? 'GZ圧縮済み' : '未圧縮') . ")\n"; 102 } 103 104 // 解凍されたファイルと未解凍のファイルの内容を直接読み込んで確認 105 echo "\n解凍後のPharアーカイブからファイル内容を読み込み:\n"; 106 echo " - docs/document1.txt (解凍済み): " . $phar['docs/document1.txt']->getContents() . "\n"; 107 echo " - reports/report.txt (まだ圧縮済み): " . $phar['reports/report.txt']->getContents() . "\n"; 108 echo " - configs/data/config.json (解凍済み): " . $phar['configs/data/config.json']->getContents() . "\n"; 109 110 } else { 111 echo " ファイルの解凍に失敗しました。\n"; 112 } 113 114 } catch (PharException $e) { 115 // Phar操作中にエラーが発生した場合の処理 116 echo "Phar操作中にエラーが発生しました: " . $e->getMessage() . "\n"; 117 } finally { 118 // 5. クリーンアップ 119 // Pharオブジェクトはファイルハンドルを保持しているため、 120 // unlinkする前に unset するか、スクリプト終了を待つ必要があります。 121 unset($phar); 122 if (file_exists($pharPath)) { 123 unlink($pharPath); 124 echo "\nPharアーカイブ '" . basename($pharPath) . "' を削除しました。\n"; 125 } 126 127 // テスト用に作成した一時ファイルを削除 128 if (file_exists($testFile1Path)) { 129 unlink($testFile1Path); 130 } 131 if (file_exists($testFile2Path)) { 132 unlink($testFile2Path); 133 } 134 if (file_exists($testFile3Path)) { 135 unlink($testFile3Path); 136 } 137 // ディレクトリはサブディレクトリから順に削除 138 if (is_dir($tempDir . 'data/')) { 139 rmdir($tempDir . 'data/'); 140 } 141 if (is_dir($tempDir)) { 142 rmdir($tempDir); 143 } 144 echo "テスト用ファイルとディレクトリをクリーンアップしました。\n"; 145 146 // phar.readonly の設定を元の状態に戻す 147 ini_set('phar.readonly', $oldReadonly); 148 echo "\n--- Phar::decompressFiles() サンプル終了 ---\n"; 149 } 150} 151 152// サンプル関数を実行します。 153demonstratePharDecompressFiles();
このPHPコードは、Phar::decompressFiles() メソッドを使用して、Pharアーカイブに格納された圧縮ファイルの中から特定のファイルだけを解凍する方法を示すものです。システムエンジニアを目指す初心者の方にも分かりやすいように、具体的な手順で構成されています。
まず、一時的なテストファイルとディレクトリを作成し、それらをGzip圧縮形式で新しいPharアーカイブに格納します。その後、decompressFiles() メソッドを呼び出し、引数 $files に解凍したいファイルのPharアーカイブ内での相対パスを配列として渡します。引数 $extension はオプションで、解凍後のファイルに新しい拡張子を付与する場合に指定しますが、このサンプルでは使用していません。このメソッドは、指定されたファイルがアーカイブ内で正常に解凍された場合は true を、一つでも失敗した場合は false をブール値で返します。コードの実行前には phar.readonly 設定を一時的に無効にしてアーカイブの作成・変更を許可し、実行後にはPharアーカイブや一時ファイルを適切に削除してクリーンアップを行います。これにより、Pharアーカイブ内の特定のファイルのみを効率的に管理する仕組みを学べます。
PHPのPhar::decompressFiles()メソッドは、Pharアーカイブ内の圧縮されたファイルを解凍します。この操作を行うには、ini_set('phar.readonly', '0')でPharアーカイブへの書き込みを許可する必要があります。解凍したいファイルのPharアーカイブ内での正確なパスを配列で指定してください。メソッドは解凍の成否をtrueまたはfalseで返すため、必ず戻り値を確認し、適切なエラーハンドリングを行うことが重要です。また、Pharオブジェクトはファイルハンドルを保持するため、アーカイブファイルを削除する前には必ずunset()でオブジェクトを解放するようにしましょう。
Phar::decompressFilesでファイル解凍する
1<?php 2 3// エラー報告を有効にします。これにより、問題発生時に詳細なエラーメッセージが表示されます。 4ini_set('display_errors', 1); 5error_reporting(E_ALL); 6 7/** 8 * Phar::decompressFiles メソッドの使用例を示します。 9 * この関数は、Pharアーカイブ(複数のファイルをまとめた単一のファイル)内の 10 * 特定の圧縮ファイルを解凍して、ファイルシステムに取り出します。 11 * 12 * システムエンジニアを目指す初心者の方へ: 13 * Pharは、PHPアプリケーションを配布するための便利な形式です。 14 * この例では、まずファイルをPharアーカイブ内に圧縮して保存し、 15 * その後、Phar::decompressFilesを使ってアーカイブ内から 16 * 特定のファイルを解凍して取り出す一連の流れを体験できます。 17 */ 18function demonstratePharDecompressFiles(): void 19{ 20 echo "Phar::decompressFiles メソッドのデモンストレーションを開始します。\n\n"; 21 22 // 1. 一時的な作業ディレクトリとファイルパスを設定 23 $tempDir = __DIR__ . '/temp_phar_test'; 24 $pharPath = $tempDir . '/my_archive.phar'; 25 // アーカイブする元のファイル内容 26 $originalContent = 'This is the original content of the file that will be compressed inside the Phar archive.'; 27 // Pharアーカイブ内のファイル名 28 $archivedFileName = 'my_compressed_file.txt'; 29 30 // 解凍後に作成されるファイルパス 31 // $extension を指定しない場合のファイル名 32 $decompressedOutputPathDefault = $tempDir . '/' . $archivedFileName; 33 // $extension を '.decompressed' と指定した場合のファイル名 34 $decompressedOutputPathWithExt = $tempDir . '/' . $archivedFileName . '.decompressed'; 35 36 // 作業ディレクトリが存在しない場合は作成します 37 if (!is_dir($tempDir)) { 38 mkdir($tempDir); 39 } 40 41 // スクリプトの実行終了時に、作成したPharファイルや解凍したファイルを 42 // 自動的に削除するクリーンアップ関数を登録します。 43 register_shutdown_function(function () use ($tempDir, $pharPath, $decompressedOutputPathDefault, $decompressedOutputPathWithExt) { 44 echo "\nクリーンアップを実行します...\n"; 45 if (file_exists($pharPath)) { 46 unlink($pharPath); // Pharファイルを削除 47 } 48 if (file_exists($decompressedOutputPathDefault)) { 49 unlink($decompressedOutputPathDefault); // 解凍されたファイルを削除 50 } 51 if (file_exists($decompressedOutputPathWithExt)) { 52 unlink($decompressedOutputPathWithExt); // 拡張子付きで解凍されたファイルを削除 53 } 54 if (is_dir($tempDir)) { 55 rmdir($tempDir); // 作業ディレクトリを削除 56 } 57 echo "クリーンアップが完了しました。\n"; 58 }); 59 60 try { 61 // 2. Pharアーカイブの作成と圧縮されたファイルの追加 62 echo "Pharアーカイブを作成し、内部にファイルをGZIP圧縮して追加します: {$pharPath}\n"; 63 64 // 新しいPharアーカイブを作成します (第二引数はファイルのパーミッション、第三引数はアーカイブのエイリアス) 65 $phar = new Phar($pharPath, 0, 'my_archive.phar'); 66 67 // PharアーカイブとしてPHPが認識するためのスタブを設定します。 68 // これはPharファイルの先頭に記述されるコードで、Pharファイルを直接実行した際の動作を定義します。 69 $phar->setStub("<?php __HALT_COMPILER(); ?>"); 70 71 // アーカイブ内にファイルを追加します。 72 // addFromString はデフォルトで圧縮を行わないため、後続の compressFiles() で圧縮します。 73 $phar->addFromString($archivedFileName, $originalContent); 74 // アーカイブ内のすべてのファイルをGZIP形式で圧縮します。 75 $phar->compressFiles(Phar::GZ); 76 77 // Pharオブジェクトをnullに設定することで、Pharアーカイブがディスクに書き込まれ、 78 // ファイルハンドルが安全に閉じられます。 79 $phar = null; 80 81 echo "Pharアーカイブ '{$pharPath}' にファイル '{$archivedFileName}' がGZIP圧縮されて追加されました。\n\n"; 82 83 // 3. 作成したPharアーカイブを読み込み、ファイルを解凍 84 echo "Pharアーカイブ '{$pharPath}' を読み込み、内部のファイルを解凍します。\n"; 85 86 // 読み取りモードで既存のPharアーカイブを開きます 87 $phar = new Phar($pharPath); 88 89 // 解凍したいPharアーカイブ内のファイルのパスを配列で指定します。 90 $filesToDecompress = [$archivedFileName]; 91 92 // --- 最初の解凍: $extension を指定しない場合 --- 93 echo " - 解凍ファイル: '{$archivedFileName}' (拡張子指定なし)\n"; 94 // decompressFiles メソッドを使用してファイルを解凍します。 95 // 第二引数 $extension を null にすると、元のファイル名で解凍されます。 96 $resultDefault = $phar->decompressFiles($filesToDecompress, null); 97 98 if ($resultDefault) { 99 echo " -> ファイル '{$archivedFileName}' がディレクトリ '{$tempDir}' に正常に解凍されました。\n"; 100 // 4. 解凍されたファイルの検証 101 if (file_exists($decompressedOutputPathDefault)) { 102 $decompressedContent = file_get_contents($decompressedOutputPathDefault); 103 if ($decompressedContent === $originalContent) { 104 echo " -> 解凍されたファイルの内容はオリジナルと一致します。\n"; 105 } else { 106 echo " -> エラー: 解凍されたファイルの内容がオリジナルと一致しません。\n"; 107 } 108 } else { 109 echo " -> エラー: 解凍されたファイル '{$decompressedOutputPathDefault}' が見つかりません。\n"; 110 } 111 } else { 112 echo " -> エラー: ファイル '{$archivedFileName}' の解凍に失敗しました。\n"; 113 } 114 115 echo "\n"; 116 117 // --- 2回目の解凍: $extension を指定する場合 --- 118 echo " - 解凍ファイル: '{$archivedFileName}' (拡張子 '.decompressed' を指定)\n"; 119 // decompressFiles メソッドは、指定された $extension を解凍後のファイル名に追加します。 120 // 例: 'my_compressed_file.txt' -> 'my_compressed_file.txt.decompressed' 121 $resultWithExtension = $phar->decompressFiles($filesToDecompress, '.decompressed'); 122 123 if ($resultWithExtension) { 124 echo " -> ファイル '{$archivedFileName}' がディレクトリ '{$tempDir}' に拡張子 '.decompressed' を付けて\n"; 125 echo " '{$decompressedOutputPathWithExt}' として正常に解凍されました。\n"; 126 // 4. 解凍されたファイルの検証 127 if (file_exists($decompressedOutputPathWithExt)) { 128 $decompressedContentWithExt = file_get_contents($decompressedOutputPathWithExt); 129 if ($decompressedContentWithExt === $originalContent) { 130 echo " -> 解凍されたファイルの内容はオリジナルと一致します (拡張子指定あり)。\n"; 131 } else { 132 echo " -> エラー: 解凍されたファイルの内容がオリジナルと一致しません (拡張子指定あり)。\n"; 133 } 134 } else { 135 echo " -> エラー: 解凍されたファイル '{$decompressedOutputPathWithExt}' が見つかりません。\n"; 136 } 137 } else { 138 echo " -> エラー: 拡張子指定ありのファイル '{$archivedFileName}' の解凍に失敗しました。\n"; 139 } 140 141 } catch (PharException $e) { 142 // Phar関連のエラー(例: ファイルアクセス権限、Pharアーカイブの破損など)をキャッチします。 143 echo "Phar 操作中にエラーが発生しました: " . $e->getMessage() . "\n"; 144 } catch (Exception $e) { 145 // その他の予期せぬエラーをキャッチします。 146 echo "予期せぬエラーが発生しました: " . $e->getMessage() . "\n"; 147 } 148} 149 150// デモンストレーション関数を実行します。 151demonstratePharDecompressFiles(); 152
Phar::decompressFilesメソッドは、PHPで複数のファイルを単一のアーカイブにまとめるPharファイルから、特定の圧縮されたファイルを解凍して、ファイルシステムに取り出す機能を提供します。
このメソッドは、第一引数に解凍したいPharアーカイブ内のファイルパスを文字列の配列として受け取ります。例えば、アーカイブ内に「document.txt」というファイルがあれば、['document.txt']のように指定します。
第二引数 $extension はオプションで、解凍後のファイル名に付加する拡張子を指定できます。この引数を省略するか null を指定した場合、ファイルは元の名前で解凍されます。もし .decompressed のように指定すると、「document.txt.decompressed」といった新しい名前でファイルが作成されます。
処理が正常に完了し、指定されたファイルがすべて解凍された場合は true が、途中で何らかの問題が発生した場合は false が戻り値として返されます。
システムエンジニアを目指す方にとって、この機能はPHPアプリケーションを配布する際に、Pharアーカイブから必要な設定ファイルやデータファイルなどを動的に取り出す場面で役立ちます。サンプルコードでは、ファイルをPharに圧縮し、その後、decompressFilesを使って元のファイル名と、拡張子を付加したファイル名の2通りで解凍する一連の流れが示されています。
Pharオブジェクトでのファイル作成後は、必ずオブジェクトをnullに設定し、リソースを解放してアーカイブを適切に書き込んでください。decompressFilesメソッドは、解凍するファイル名を配列で渡し、第二引数で任意の拡張子を付与可能です。このメソッドの戻り値は解凍の成否を示すブール値なので、必ず確認しましょう。ファイルアクセス権限の問題やPharアーカイブの破損といったエラーに備え、try-catchブロックでPharExceptionを捕捉し、適切にエラー処理を行うことが必須です。また、一時的に作成されるファイルは、register_shutdown_functionなどを利用してスクリプト終了時に確実に削除することをお勧めします。