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

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

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

作成日: 更新日:

基本的な使い方

extractToメソッドは、PharDataオブジェクトが表すアーカイブ(圧縮ファイル)の内容を、指定したディレクトリに展開(解凍)するメソッドです。このメソッドは、主に.tar.zipといった形式のアーカイブファイルから、内部に含まれるファイルやディレクトリを、プログラムを通じてディスク上の特定の場所に取り出したい場合に利用されます。

第一引数$directoryには、アーカイブの内容を展開する先のパスを指定します。もし指定したディレクトリが存在しない場合でも、extractToメソッドは自動的にそのディレクトリを作成しようと試みます。

第二引数$filesは省略可能で、特定のファイルやディレクトリのみを抽出したい場合に、そのファイルパスを文字列または文字列の配列として渡します。この引数を省略した場合は、アーカイブ内の全てのコンテンツが展開されます。

第三引数$overwriteも省略可能な真偽値で、展開先に同名のファイルが既に存在する場合に、そのファイルを上書きするかどうかを制御します。trueを指定すると既存のファイルは上書きされますが、デフォルトのfalseでは上書きされず、エラーとなる場合があります。

メソッドの実行が成功するとtrueが返され、何らかの理由で展開に失敗した場合にはfalseが返されます。例えば、展開先のディレクトリへの書き込み権限がない場合や、アーカイブファイル自体に問題がある場合などに失敗することがあります。

構文(syntax)

1<?php
2$pharData->extractTo('/path/to/extract/directory');
3?>

引数(parameters)

string $directory, array|string|null $files = null, bool $overwrite = false

  • string $directory: Pharアーカイブを展開する先のディレクトリパス
  • array|string|null $files = null: 展開するファイルまたはディレクトリのパスを指定します。省略した場合、アーカイブ内のすべてのファイルが展開されます。
  • bool $overwrite = false: 展開先に同名のファイルが存在する場合に上書きするかどうかを指定します。trueで上書きします。

戻り値(return)

bool

指定されたパスへアーカイブを展開できた場合は true、失敗した場合は false を返します。

サンプルコード

PHP PharData::extractToでZIP展開する

1<?php
2
3// このサンプルコードは、PHPのPharData::extractToメソッドを使用して、ZIP形式のアーカイブファイルから
4// 内容を展開する方法を示します。
5// 単体で動作するように、一時的なZIPアーカイブの作成と展開、そしてクリーンアップまでを行います。
6
7// 1. 必要なパスの定義とクリーンアップ関数の準備
8$sourceDirPath = __DIR__ . '/temp_source_for_zip'; // ZIPアーカイブ作成用の一時ディレクトリ
9$zipFilePath = __DIR__ . '/example_archive.zip';   // 作成するZIPアーカイブのパス
10$extractDirPath = __DIR__ . '/temp_extracted_data'; // 展開先の一時ディレクトリ
11
12/**
13 * 指定されたパスのファイルまたはディレクトリを再帰的に削除する関数。
14 * @param array $paths 削除するパスの配列
15 */
16function cleanup_temp_files(array $paths): void
17{
18    foreach ($paths as $path) {
19        if (is_dir($path)) {
20            // ディレクトリとその中身を再帰的に削除
21            $it = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
22            $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
23            foreach ($files as $file) {
24                if ($file->isDir()) {
25                    rmdir($file->getRealPath());
26                } else {
27                    unlink($file->getRealPath());
28                }
29            }
30            rmdir($path);
31        } elseif (file_exists($path)) {
32            unlink($path);
33        }
34    }
35}
36
37// 既存の一時ファイルを事前にクリーンアップ
38cleanup_temp_files([$sourceDirPath, $zipFilePath, $extractDirPath]);
39
40// 2. PharDataで展開するためのZIPアーカイブを準備
41// ZipArchiveクラスを使用して一時的なZIPアーカイブを作成します。
42// これにより、「php ziparchive extractto」というキーワードに関連付けられます。
43// PharDataクラスは、ZIP形式のアーカイブも扱うことができます。
44
45// ZIPアーカイブの元となるファイル群を作成
46if (!mkdir($sourceDirPath) && !is_dir($sourceDirPath)) {
47    echo "エラー: ソースディレクトリを作成できませんでした。\n";
48    exit(1);
49}
50if (!mkdir($sourceDirPath . '/subfolder') && !is_dir($sourceDirPath . '/subfolder')) {
51    echo "エラー: サブフォルダを作成できませんでした。\n";
52    cleanup_temp_files([$sourceDirPath]);
53    exit(1);
54}
55file_put_contents($sourceDirPath . '/file1.txt', 'これはファイル1の内容です。');
56file_put_contents($sourceDirPath . '/subfolder/file2.txt', 'これはサブフォルダ内のファイル2の内容です。');
57
58$zip = new ZipArchive();
59if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
60    // ソースディレクトリ内のファイルとフォルダをZIPに追加
61    $files = new RecursiveIteratorIterator(
62        new RecursiveDirectoryIterator($sourceDirPath, RecursiveDirectoryIterator::SKIP_DOTS),
63        RecursiveIteratorIterator::SELF_FIRST
64    );
65    foreach ($files as $file) {
66        $filePath = $file->getRealPath();
67        // ZIP内での相対パスを生成
68        $relativePath = substr($filePath, strlen($sourceDirPath) + 1);
69        if ($file->isDir()) {
70            $zip->addEmptyDir($relativePath);
71        } else {
72            $zip->addFile($filePath, $relativePath);
73        }
74    }
75    $zip->close();
76    echo "一時的なZIPアーカイブ '" . basename($zipFilePath) . "' を作成しました。\n";
77} else {
78    echo "エラー: ZIPアーカイブの作成に失敗しました。\n";
79    cleanup_temp_files([$sourceDirPath]);
80    exit(1);
81}
82
83// 3. PharData::extractTo メソッドでアーカイブを展開
84
85// 展開先ディレクトリが存在しない場合は作成
86if (!is_dir($extractDirPath) && !mkdir($extractDirPath, 0777, true)) {
87    echo "エラー: 展開先ディレクトリを作成できませんでした。\n";
88    cleanup_temp_files([$sourceDirPath, $zipFilePath]);
89    exit(1);
90}
91
92echo "\n'" . basename($zipFilePath) . "' を '" . basename($extractDirPath) . "' へ展開します...\n";
93
94try {
95    // PharDataオブジェクトを作成
96    // ZIPアーカイブのパスを指定します。
97    $phar = new PharData($zipFilePath);
98
99    // extractToメソッドを使ってアーカイブの内容を展開します。
100    // 引数1: string $directory (必須) - 展開先のディレクトリパス
101    // 引数2: array|string|null $files (オプション) - 展開するファイルまたはディレクトリ。nullの場合は全て展開。
102    // 引数3: bool $overwrite (オプション) - 既存のファイルを上書きするかどうか。false (デフォルト) は上書きしない。
103    $isExtracted = $phar->extractTo($extractDirPath, null, false);
104
105    if ($isExtracted) {
106        echo "ファイルの展開に成功しました!\n";
107        echo "展開されたファイル:\n";
108        // 展開されたファイルの一覧を表示して確認
109        $extractedFiles = new RecursiveIteratorIterator(
110            new RecursiveDirectoryIterator($extractDirPath, RecursiveDirectoryIterator::SKIP_DOTS),
111            RecursiveIteratorIterator::SELF_FIRST
112        );
113        foreach ($extractedFiles as $file) {
114            if ($file->isFile()) {
115                echo "- " . substr($file->getRealPath(), strlen($extractDirPath) + 1) . "\n";
116            }
117        }
118
119        // 特定のファイルのみを展開する例(コメント解除して試すことができます)
120        // echo "\n'file1.txt' のみ展開を試みます...\n";
121        // cleanup_temp_files([$extractDirPath]); // 再度展開するために既存のファイルを削除
122        // mkdir($extractDirPath, 0777, true);
123        // $isPartialExtracted = $phar->extractTo($extractDirPath, ['file1.txt'], true);
124        // if ($isPartialExtracted) {
125        //     echo "特定のファイル(file1.txt)の展開に成功しました。\n";
126        // } else {
127        //     echo "特定のファイルの展開に失敗しました。\n";
128        // }
129
130    } else {
131        echo "ファイルの展開に失敗しました。\n";
132    }
133} catch (Exception $e) {
134    echo "展開中にエラーが発生しました: " . $e->getMessage() . "\n";
135} finally {
136    // 4. 使用後の一時ファイルとディレクトリのクリーンアップ
137    echo "\n一時ファイルをクリーンアップしています...\n";
138    cleanup_temp_files([$sourceDirPath, $zipFilePath, $extractDirPath]);
139    echo "クリーンアップが完了しました。\n";
140}
141
142?>

PHP 8のPharData::extractToメソッドは、ZIP形式を含むアーカイブファイルから内容を指定したディレクトリへ展開するために使用されます。PharDataクラスは、PHP標準の拡張機能として提供され、キーワードにあるZipArchiveクラスと同様にZIPアーカイブを扱うことができます。このメソッドは、システムエンジニアを目指す方にとって、アーカイブ操作の基本的なスキルとなるでしょう。

extractToメソッドの最初の引数$directoryには、ファイルを展開したいディレクトリのパスを文字列で指定します。2番目の引数$filesはオプションで、特定のファイルやディレクトリのみを展開したい場合に、その名前を文字列または配列で指定します。この引数を省略するかnullを指定すると、アーカイブ内のすべての内容が展開されます。最後の引数$overwriteもオプションで、展開先に同名のファイルが存在する場合に、それを上書きするかどうかを真偽値で指定します。デフォルトはfalseで、既存のファイルを上書きしません。

メソッドがファイルの展開に成功した場合はtrueを、失敗した場合はfalseを戻り値として返します。このサンプルコードでは、一時的なZIPアーカイブをZipArchiveクラスで作成し、そのアーカイブをPharData::extractToメソッドで安全に展開し、最終的に一時ファイルをクリーンアップする一連の流れが示されています。これにより、実際のシステム開発でアーカイブファイルを扱う際の具体的な手順を理解することができます。

PHPのPharDataクラスはPhar形式だけでなく、ZIP形式のアーカイブも展開できます。extractToメソッドを利用する際は、まず展開先のディレクトリが事前に存在している必要がありますので、必要に応じてmkdirなどで作成してください。第3引数$overwriteは、展開先に同名ファイルが存在する場合の上書き挙動を決定します。デフォルトはfalse(上書きしない)のため、既存ファイルがある場合は展開に失敗する可能性があります。常に最新にしたい場合はtrueを設定してください。また、信頼できないアーカイブを展開する際は、悪意のあるファイルが含まれる可能性があり、セキュリティ上のリスクがありますので、展開先のパス制御に十分注意し、try-catchブロックで例外を捕捉するエラーハンドリングも重要です。

PHP PharData::extractToでzip/tarを解凍する

1<?php
2
3/**
4 * PharData::extractTo メソッドの使用例を示します。
5 *
6 * この関数は、一時的なtarアーカイブを作成し、その中からファイルを
7 * 指定されたディレクトリに抽出する方法を、システムエンジニアを目指す初心者にも
8 * 分かりやすく示します。
9 *
10 * @return void
11 */
12function exampleExtractPharData(): void
13{
14    // 一時的なアーカイブファイル名と、抽出先のディレクトリ名を設定します。
15    // これらのファイルやディレクトリは、スクリプトが実行されるディレクトリに作成されます。
16    $archiveName = 'test_archive.tar';
17    $extractDir = 'extracted_files';
18    // アーカイブに含める元のファイルがある一時ディレクトリを設定します。
19    $tempSourceDir = __DIR__ . DIRECTORY_SEPARATOR . 'temp_source_for_archive';
20
21    echo "--- PharData::extractTo サンプル開始 ---\n";
22
23    // 抽出先ディレクトリの準備
24    // 既に存在する場合は、古い内容と衝突しないように削除し、新しく作成します。
25    if (file_exists($extractDir)) {
26        deleteDirectory($extractDir);
27    }
28    if (!mkdir($extractDir, 0777, true)) {
29        echo "エラー: 抽出先ディレクトリ '{$extractDir}' の作成に失敗しました。\n";
30        return;
31    }
32    echo "抽出先ディレクトリ '{$extractDir}' を作成しました。\n";
33
34    // アーカイブ作成用の一時ディレクトリを準備
35    // このディレクトリ内のファイルがアーカイブに格納されます。
36    if (file_exists($tempSourceDir)) {
37        deleteDirectory($tempSourceDir);
38    }
39    if (!mkdir($tempSourceDir, 0777, true)) {
40        echo "エラー: アーカイブ作成用一時ディレクトリ '{$tempSourceDir}' の作成に失敗しました。\n";
41        deleteDirectory($extractDir); // 抽出先ディレクトリもクリーンアップ
42        return;
43    }
44    echo "アーカイブ作成用一時ディレクトリ '{$tempSourceDir}' を作成しました。\n";
45
46    // テスト用のダミーファイルとサブディレクトリを一時ディレクトリ内に作成します。
47    // これらがアーカイブに格納される対象となります。
48    $file1Path = $tempSourceDir . DIRECTORY_SEPARATOR . 'file1.txt';
49    $subDirPath = $tempSourceDir . DIRECTORY_SEPARATOR . 'sub_folder';
50    $file2Path = $subDirPath . DIRECTORY_SEPARATOR . 'file2.txt';
51
52    if (!mkdir($subDirPath, 0777, true)) {
53        echo "エラー: サブディレクトリ '{$subDirPath}' の作成に失敗しました。\n";
54        deleteDirectory($tempSourceDir);
55        deleteDirectory($extractDir);
56        return;
57    }
58    file_put_contents($file1Path, "これはファイル1の内容です。\n");
59    file_put_contents($file2Path, "これはサブフォルダー内のファイル2の内容です。\n");
60    echo "テスト用のダミーファイルとディレクトリを作成しました: '{$file1Path}', '{$file2Path}'\n";
61
62    // PharDataオブジェクトを使用して、tarアーカイブを作成し、ファイルを格納します。
63    // PharDataは、zipやtarなどのデータアーカイブを扱うのに適しています。
64    try {
65        // 新しいPharDataアーカイブを作成します。
66        // ファイルのパスと、アーカイブ形式を指定できます(省略時はtar)。
67        $pharData = new PharData($archiveName);
68
69        // buildFromDirectoryメソッドを使って、指定したディレクトリの内容をアーカイブに追加します。
70        // 第1引数: アーカイブに追加するソースディレクトリ
71        // 第2引数: (オプション) アーカイブ内のファイル名に適用する正規表現
72        $pharData->buildFromDirectory($tempSourceDir);
73        echo "テストアーカイブ '{$archiveName}' を作成し、ファイルを追加しました。\n";
74
75    } catch (Exception $e) {
76        echo "エラー: アーカイブの作成に失敗しました: " . $e->getMessage() . "\n";
77        // エラー発生時のクリーンアップ
78        deleteDirectory($tempSourceDir);
79        deleteDirectory($extractDir);
80        if (file_exists($archiveName)) {
81            unlink($archiveName);
82        }
83        return;
84    }
85
86    // 作成したアーカイブからファイルを抽出します。
87    try {
88        // 既存のアーカイブを開くために、PharDataオブジェクトを再度インスタンス化します。
89        // (上記で作成した$pharDataオブジェクトをそのまま使うことも可能です。)
90        $pharDataToExtract = new PharData($archiveName);
91        echo "アーカイブ '{$archiveName}' を抽出用に開きました。\n";
92
93        // extractTo メソッドを使って、アーカイブの内容を指定されたディレクトリに抽出します。
94        // 第1引数: ファイルを抽出する先のディレクトリのパス ('{$extractDir}')
95        // 第2引数: 抽出したいファイルやディレクトリのリスト。
96        //          nullを指定すると、アーカイブ内のすべてのファイルが抽出されます。
97        //          特定のファイルのみを抽出したい場合は、ファイルパスの配列または文字列を指定します。
98        // 第3引数: 抽出先に同名のファイルが既に存在する場合に上書きするかどうか (trueで上書き)
99        $extractionSuccessful = $pharDataToExtract->extractTo($extractDir, null, true);
100
101        if ($extractionSuccessful) {
102            echo "アーカイブの内容を '{$extractDir}' に正常に抽出しました。\n";
103
104            // 抽出されたファイルが実際に存在するかを確認します。
105            $extractedFile1 = $extractDir . DIRECTORY_SEPARATOR . 'file1.txt';
106            $extractedFile2 = $extractDir . DIRECTORY_SEPARATOR . 'sub_folder' . DIRECTORY_SEPARATOR . 'file2.txt';
107
108            if (file_exists($extractedFile1) && file_exists($extractedFile2)) {
109                echo "ファイル 'file1.txt' と 'sub_folder/file2.txt' が抽出ディレクトリに存在することを確認しました。\n";
110            } else {
111                echo "警告: 抽出された一部またはすべてのファイルが見つかりません。\n";
112            }
113        } else {
114            echo "エラー: アーカイブの抽出に失敗しました。\n";
115        }
116    } catch (Exception $e) {
117        echo "エラー: アーカイブの抽出中に例外が発生しました: " . $e->getMessage() . "\n";
118    } finally {
119        // 後処理: テスト用に作成したファイルやディレクトリを削除してクリーンアップします。
120        echo "クリーンアップを開始します。\n";
121        deleteDirectory($tempSourceDir); // アーカイブ作成元の一時ディレクトリを削除
122        deleteDirectory($extractDir);     // 抽出先ディレクトリを削除
123        if (file_exists($archiveName)) {
124            unlink($archiveName); // アーカイブファイルを削除
125            echo "アーカイブファイル '{$archiveName}' を削除しました。\n";
126        }
127        echo "クリーンアップが完了しました。\n";
128    }
129
130    echo "--- PharData::extractTo サンプル終了 ---\n";
131}
132
133/**
134 * 指定されたディレクトリとその内容を再帰的に削除します。
135 * ファイルシステムの操作のため、使用する際は注意が必要です。
136 *
137 * @param string $dirPath 削除するディレクトリのパス。
138 * @return bool 成功した場合はtrue、失敗した場合はfalse。
139 */
140function deleteDirectory(string $dirPath): bool
141{
142    // ディレクトリが存在しない場合は何もしません。
143    if (!is_dir($dirPath)) {
144        return false;
145    }
146
147    // ディレクトリ内のすべてのファイルとサブディレクトリを取得します。
148    // GLOB_BRACE は {*,.[!.]*,..[!.]*} のようなパターンを拡張し、
149    // '.' (現在のディレクトリ) と '..' (親ディレクトリ) を除外します。
150    $files = glob($dirPath . DIRECTORY_SEPARATOR . '{*,.[!.]*,..[!.]*}', GLOB_BRACE);
151    foreach ($files as $file) {
152        // . と .. ディレクトリは明示的にスキップします。
153        if ($file === $dirPath . DIRECTORY_SEPARATOR . '.' || $file === $dirPath . DIRECTORY_SEPARATOR . '..') {
154            continue;
155        }
156        if (is_dir($file)) {
157            // サブディレクトリの場合、再帰的に削除します。
158            deleteDirectory($file);
159        } else {
160            // ファイルの場合、削除します。
161            unlink($file);
162        }
163    }
164    // ディレクトリが空になったら、そのディレクトリ自体を削除します。
165    return rmdir($dirPath);
166}
167
168// サンプル関数の実行
169// このスクリプトを実行すると、一時的なファイルとディレクトリが作成され、
170// その後クリーンアップされます。
171exampleExtractPharData();
172
173?>

PHP 8のPharData::extractToメソッドは、.tar.zipなどのデータアーカイブファイルから、中のファイルを指定したディレクトリへ取り出す(抽出する)ための機能です。このメソッドは、アーカイブされた複数のファイルを一括で展開したい場合に非常に役立ちます。

第一引数$directoryには、抽出したファイルを保存する先のディレクトリパスを文字列で指定します。このディレクトリは、通常、抽出前に作成しておく必要があります。 第二引数$filesはオプションで、アーカイブ内のどのファイルを抽出するかを指定します。特定のファイル名(文字列)や、複数のファイル名(配列)を指定でき、nullを指定した場合はアーカイブ内のすべてのファイルが抽出されます。 第三引数$overwriteもオプションで、抽出先のディレクトリに同名のファイルが既に存在する場合に、上書きするかどうかを真偽値(trueで上書き、falseで上書きしない)で設定します。 このメソッドは、ファイル抽出が成功した場合はtrueを、失敗した場合はfalseを戻り値として返します。

提供されたサンプルコードでは、まず一時的なtarアーカイブファイルを作成し、その中にいくつかのダミーファイルを格納しています。その後、作成したアーカイブをPharDataオブジェクトとして開き直し、extractToメソッドを使用して、アーカイブ内のすべてのファイルをextracted_filesというディレクトリに抽出し、上書きも許可しています。この機能は、ソフトウェアのインストール処理やデータ展開など、ファイル管理が必要なシステム開発の様々な場面で活用できます。

PHPのPharData::extractToは、tarなどのアーカイブからファイルを指定ディレクトリへ抽出する際に使われます。最も重要なのは、抽出先のディレクトリパスを正確に指定することです。また、抽出先に同名のファイルが既に存在する場合に、上書きして良いかを第3引数$overwritetrueとして明示的に指定する必要があります。サンプルコードのように、ファイル操作は予期せぬエラーが発生しやすいため、try-catchでエラーを適切に処理し、finallyブロックで作成した一時ファイルやディレクトリを確実に削除する「クリーンアップ処理」を忘れずに行うことが、安定したプログラム運用のために非常に大切です。特定のファイルのみを抽出したい場合は、第2引数$filesにファイルパスの配列または文字列を指定できます。

関連コンテンツ