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

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

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

作成日: 更新日:

基本的な使い方

webPharメソッドは、PharアーカイブをWebアプリケーションとして機能させるための設定を行うメソッドです。このメソッドを使用することで、単一のPharファイルを、Webサーバー上で複数のファイルやディレクトリを持つアプリケーションのように振る舞わせることが可能になります。

具体的には、Webサーバーからのリクエストに対して、Pharアーカイブ内部のどのファイルがアプリケーションのエントリーポイント、つまり最初に処理を開始するフロントコントローラとして動作するかを指定できます。これにより、ウェブサイトの全てのアクセスを一つのファイルで受け止め、内部で適切な処理に振り分ける、といった仕組みをPharアーカイブに組み込めます。

さらに、存在しないURLへのアクセスなど、指定されたファイルが見つからなかった場合(HTTP 404エラー)に、表示するカスタムエラーページや、その代わりの処理を設定することも可能です。例えば、「指定されたページが見つかりません」といったメッセージを表示する専用のファイルを設定できます。

この機能は、Webサーバー側で複雑なリライトルールを設定することなく、Pharアーカイブ自身が内部でURLのルーティングやエラー処理を制御するようになることを意味します。例えば、index.phpをフロントコントローラとし、存在しないパスへのアクセスを404.phpに転送するといった動作を、単一のPharファイルで実現できます。これにより、PHPで開発されたウェブアプリケーションを、一つの実行可能ファイルとして簡単に配布し、デプロイプロセスを大幅に簡素化したい場合に非常に有用です。引数には、これらのインデックスファイル名や404エラー時に表示するファイル名を指定できます。

構文(syntax)

1<?php
2
3// Pharオブジェクトのインスタンスを準備します。
4// ここでは、新しいPharアーカイブ 'my_application.phar' を作成する例を示します。
5$phar = new Phar('my_application.phar');
6
7// Phar::webPhar() メソッドを呼び出して、ウェブアプリケーション用のスタブコードを生成します。
8// 全ての引数はオプションです。PHP 8以降では名前付き引数を使用して、
9// 必要な引数のみを分かりやすく指定できます。
10$webPharStubCode = $phar->webPhar(
11    alias: 'myWebApp',    // ウェブアプリケーションのエイリアス
12    index: 'index.php'    // デフォルトのインデックスファイル
13);
14
15?>

引数(parameters)

?string $alias = null, ?string $index = null, ?string $fileNotFoundScript = null, ?array $mimeTypes = null, ?callable $rewrite = null

  • ?string $alias = null: Pharアーカイブにアクセスするためのエイリアス名(省略可能)。
  • ?string $index = null: Pharアーカイブのルートとなるインデックスファイル名(省略可能)。
  • ?string $fileNotFoundScript = null: ファイルが見つからなかった場合に実行するスクリプトのパス(省略可能)。
  • ?array $mimeTypes = null: ファイル拡張子とMIMEタイプのマッピング配列(省略可能)。
  • ?callable $rewrite = null: URL書き換えコールバック関数(省略可能)。

戻り値(return)

void

Phar::webPhar は、Phar アーカイブを Web サーバー経由で公開するためのストリームラッパーを登録します。このメソッドは戻り値を返しません。

サンプルコード

PHP Phar::webPharでWebサーバーを構築する

1<?php
2
3// このスクリプトは、Pharアーカイブを作成し、
4// そのアーカイブがウェブサーバーとして動作するための設定を行う方法を示します。
5// システムエンジニアを目指す初心者向けに、Phar::webPharの基本的な使い方に焦点を当てています。
6
7// 注意: このスクリプトを実行するには、php.iniで 'phar.readonly' を '0' に設定する必要があります。
8// 例: php -d phar.readonly=0 create_phar.php
9
10// Pharファイルを作成するためのパス
11$pharPath = __DIR__ . '/phar_test.phar';
12// Pharアーカイブに含めるファイルのための一時ディレクトリ
13$tempDir = __DIR__ . '/phar_contents';
14
15// 以前に作成されたPharファイルと一時ディレクトリをクリーンアップします。
16// 単体で複数回実行しても問題ないようにするためです。
17if (file_exists($pharPath)) {
18    unlink($pharPath);
19}
20if (file_exists($tempDir)) {
21    $it = new RecursiveDirectoryIterator($tempDir, 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($tempDir);
31}
32
33// Pharアーカイブに含めるファイルを一時ディレクトリに作成します。
34// これらはPharがウェブサーバーとして動作したときに提供されるファイルです。
35mkdir($tempDir);
36file_put_contents($tempDir . '/index.php', '<?php echo "<h1>Hello from Phar!</h1><p>This is index.php inside the Phar archive.</p>";');
37file_put_contents($tempDir . '/test.php', '<?php echo "<h2>Test Page</h2><p>This is test.php inside the Phar archive.</p>";');
38file_put_contents($tempDir . '/404.php', '<?php http_response_code(404); echo "<h1>404 Not Found</h1><p>File not found in Phar!</p>";');
39
40try {
41    // Pharアーカイブを作成します。
42    // 第二引数はフラグで、Phar::buildFromDirectory() でファイルを追加する際に使用されます。
43    // 第三引数はPharアーカイブのエイリアスで、Phar::mapPhar() で参照されます。
44    $phar = new Phar($pharPath, FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME, 'phar_test.phar');
45
46    // Pharファイルの書き込みを可能にするためにバッファリングを開始します。
47    $phar->startBuffering();
48
49    // 一時ディレクトリ内のすべてのファイルをPharアーカイブに追加します。
50    $phar->buildFromDirectory($tempDir);
51
52    // Pharアーカイブがウェブサーバーとして動作するための「スタブ」を設定します。
53    // このスタブは、PharファイルがHTTPリクエストによって実行されたときに最初に実行されるPHPコードです。
54    $stub = <<<'EOD'
55<?php
56// Phar::mapPhar() を呼び出して、このPharアーカイブにエイリアスを設定します。
57// ここでは、Pharファイル名自体をエイリアスとして使用します。
58Phar::mapPhar('phar_test.phar');
59
60// Phar::webPhar() を呼び出して、ウェブサーバーとしての動作を設定します。
61// このメソッドがHTTPリクエストをPharアーカイブ内部のファイルにルーティングします。
62//
63// 引数:
64// 1. $alias: Pharアーカイブのエイリアス(Phar::mapPharで設定したものと一致させる)
65// 2. $index: ルートURL(例: http://localhost/phar_test.phar/)にアクセスしたときにデフォルトで表示するファイル
66// 3. $fileNotFoundScript: 要求されたファイルがPharアーカイブ内に見つからなかった場合に実行されるスクリプト
67Phar::webPhar(
68    'phar_test.phar',      // エイリアス: このPharファイルの名前
69    'index.php',           // インデックスファイル: デフォルトで表示するファイル
70    '404.php'              // 404スクリプト: ファイルが見つからない場合に実行
71);
72
73// __HALT_COMPILER(); はPharアーカイブの末尾を示し、この行以降はアーカイブのバイナリデータです。
74__HALT_COMPILER();
75EOD;
76
77    // 作成したスタブをPharアーカイブに設定します。
78    $phar->setStub($stub);
79
80    // Pharファイルの書き込みを終了し、変更を保存します。
81    $phar->stopBuffering();
82
83    echo "Pharアーカイブ '{$pharPath}' が正常に作成されました。\n";
84    echo "このPharファイルをウェブサーバーのドキュメントルートに配置し、\n";
85    echo "ブラウザでアクセスすることで動作を確認できます。\n\n";
86    echo "例:\n";
87    echo " - http://localhost/phar_test.phar/             (index.phpが表示されます)\n";
88    echo " - http://localhost/phar_test.phar/index.php    (index.phpが表示されます)\n";
89    echo " - http://localhost/phar_test.phar/test.php     (test.phpが表示されます)\n";
90    echo " - http://localhost/phar_test.phar/nonexistent  (404.phpが表示されます)\n";
91
92} catch (Exception $e) {
93    echo "Pharアーカイブの作成中にエラーが発生しました: " . $e->getMessage() . "\n";
94    // エラー発生時は一時ディレクトリを削除しないことで、デバッグを容易にする場合があります。
95} finally {
96    // 一時ディレクトリをクリーンアップします。
97    if (file_exists($tempDir)) {
98        $it = new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS);
99        $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
100        foreach ($files as $file) {
101            if ($file->isDir()) {
102                rmdir($file->getRealPath());
103            } else {
104                unlink($file->getRealPath());
105            }
106        }
107        rmdir($tempDir);
108    }
109}
110

PHP 8のPhar::webPharメソッドは、作成したPharアーカイブをウェブサーバーとして機能させるためのルーティング設定を行う際に使用します。このメソッドはPharアーカイブ内部のスタブ(Pharファイルが実行された際に最初に読み込まれるコード)内で呼び出すことで、HTTPリクエストをアーカイブ内の適切なファイルへ振り分けられるようにします。

引数について、$aliasはPhar::mapPhar()で設定したPharアーカイブのエイリアスを指定し、この名前でアーカイブが認識されます。$indexは、例えばURLのルート(例: http://localhost/my.phar/)にアクセスされた場合にデフォルトで表示するファイル名を設定します。$fileNotFoundScriptは、要求されたファイルがアーカイブ内に存在しなかった際に実行する、404エラーページのようなスクリプトを指定します。$mimeTypesや$rewriteといった他の引数もありますが、これらはより高度な設定で利用されます。

戻り値はvoidであり、このメソッド自体は何も値を返さず、ウェブサーバーとしてのルーティング設定を完了させる役割を担います。これにより、単一のPharファイルを配置するだけで、ウェブサイトやアプリケーションを簡単に展開できるようになります。

Pharファイルを作成するには、まずphp.iniでphar.readonlyを0に設定する必要があります。これによりファイルの書き込みが可能になります。Phar::webPharを呼び出す際には、スタブ内でPhar::mapPharで設定したエイリアスと一致させるように注意してください。indexやfileNotFoundScriptのパスは、Pharアーカイブのルートからの相対パスで指定します。スタブの末尾には__HALT_COMPILER();を必ず記述してください。このメソッドはPharアーカイブを単一のファイルとしてウェブサーバーで動作させる機能であり、実際のウェブサーバー設定でPHPがPharファイルをスクリプトとして適切に実行できるよう環境を整えることが重要です。セキュリティ面も考慮し、アーカイブの内容は慎重に決定してください。

Phar::webPharでWebAPIを作成する

1<?php
2
3/**
4 * Phar::webPhar メソッドを使用して、Web APIとして機能するPharアーカイブを作成するスクリプトです。
5 *
6 * このスクリプトは以下の手順を実行します:
7 * 1. 新しいPharアーカイブを作成します。
8 * 2. アーカイブ内にWeb APIのエントリポイントとなる 'index.php' ファイルを埋め込みます。
9 * 3. Phar::webPhar メソッドを呼び出して、WebサーバーでPharが適切に動作するための設定を行います。
10 * 4. Pharアーカイブを保存し、実行方法を案内します。
11 *
12 * 実行方法:
13 * 1. このファイルを `create_api_phar.php` として保存し、実行します。
14 *    `php create_api_phar.php`
15 * 2. `my_api.phar` というファイルが作成されます。
16 * 3. 作成されたPharファイルをPHP組み込みサーバーで起動します。
17 *    `php -S 0.0.0.0:8000 my_api.phar`
18 * 4. ブラウザやcurlで以下のURLにアクセスして、Web APIの動作を確認してください。
19 *    - `http://localhost:8000/api/users` (GET)
20 *    - `http://localhost:8000/api/hello` (GET)
21 */
22
23// 作成するPharアーカイブのファイル名
24$pharFileName = 'my_api.phar';
25
26// 既存のPharファイルがあれば削除(テスト用)
27if (file_exists($pharFileName)) {
28    unlink($pharFileName);
29}
30// 圧縮されたPharファイルも削除(テスト用)
31if (file_exists($pharFileName . '.gz')) {
32    unlink($pharFileName . '.gz');
33}
34
35try {
36    // 新しいPharアーカイブを作成します。
37    // Phar::CREATE: ファイルが存在しない場合に作成します。
38    // FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME:
39    // ファイルを追加する際に、ファイル情報とファイル名をPhar内部でどのように扱うかを定義します。
40    $phar = new Phar(
41        $pharFileName,
42        FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME,
43        $pharFileName
44    );
45
46    // Pharアーカイブへの書き込みを開始します。
47    $phar->startBuffering();
48
49    // PharアーカイブにWeb APIのエントリポイントとなる 'index.php' を追加します。
50    // このファイルがPharがWebサーバーとして起動された際にリクエストを処理します。
51    $phar->addFromString('index.php', <<<PHP
52<?php
53// Pharアーカイブ内部でWebリクエストを処理するエントリポイント
54
55header('Content-Type: application/json');
56
57\$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
58\$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
59
60// 簡単なルーティングとレスポンスの例
61if (\$requestUri === '/api/users' && \$method === 'GET') {
62    echo json_encode([
63        ['id' => 1, 'name' => 'Alice'],
64        ['id' => 2, 'name' => 'Bob']
65    ]);
66} elseif (\$requestUri === '/api/hello' && \$method === 'GET') {
67    echo json_encode(['message' => 'Hello from Phar API!']);
68} else {
69    http_response_code(404);
70    echo json_encode(['error' => 'Not Found', 'path' => \$requestUri]);
71}
72
73// 内部でのエラー表示などを防ぐため、明示的に終了
74exit;
75PHP
76    );
77
78    // Phar::webPhar メソッドを呼び出し、WebサーバーとしてPharを機能させます。
79    // 第1引数: エイリアス (nullにするとPharファイル名が使われます)
80    // 第2引数: WebリクエストのエントリポイントとなるPhar内部のファイル名
81    //           この例では、すべてのリクエストをPhar内の 'index.php' が処理します。
82    $phar->webPhar(null, 'index.php');
83
84    // アーカイブの書き込みを終了し、Pharファイルを保存します。
85    $phar->stopBuffering();
86
87    echo "Pharアーカイブ '{$pharFileName}' が正常に作成されました。\n";
88    echo "\nWeb APIとして実行するには、PHP組み込みサーバーを使用してください。\n";
89    echo "例: php -S 0.0.0.0:8000 {$pharFileName}\n";
90    echo "サーバー起動後、ブラウザやcurlで以下のURLにアクセスしてみてください:\n";
91    echo "  - http://localhost:8000/api/users\n";
92    echo "  - http://localhost:8000/api/hello\n";
93
94} catch (Exception $e) {
95    echo "Phar作成中にエラーが発生しました: " . $e->getMessage() . "\n";
96    // エラー発生時に作成途中のPharファイルを削除
97    if (file_exists($pharFileName)) {
98        unlink($pharFileName);
99    }
100}

このPHPサンプルコードは、Phar::webPharメソッドを利用して、単一ファイルで配布可能なWeb APIを作成する手順を示しています。Phar拡張機能は、複数のPHPファイルや関連リソースを一つのアーカイブにまとめ、あたかも一つのPHPファイルのように実行可能にする機能を提供します。

Phar::webPharメソッドは、作成したPharアーカイブをWebサーバーのコンテキストで動作させるための設定を行います。これにより、PharファイルがWebサーバーとして直接リクエストに応答できるようになります。サンプルコードでは、第2引数$indexに'index.php'を指定しており、これはWebサーバーからのすべてのリクエストがPharアーカイブ内部のindex.phpファイルによって処理されることを意味します。このindex.phpが、リクエストURIやメソッドに応じて適切なJSONレスポンスを返す簡易的なWeb APIとして機能します。

その他の引数として、$aliasはPharファイルに別名を付ける、$fileNotFoundScriptは存在しないパスへのアクセス時のスクリプト、$mimeTypesはMIMEタイプの設定、$rewriteはURL書き換えルールを定義できますが、これらはすべて省略可能です。このメソッドはvoidを返すため、直接的な戻り値はなく、Pharオブジェクトの内部的なWebサーバー設定を完了させます。

スクリプトを実行するとmy_api.pharファイルが生成され、これをPHP組み込みサーバーなどで起動することで、http://localhost:8000/api/usersのようなURLでWeb APIとして機能するPharの動作を確認できます。これにより、Webアプリケーションをより手軽に配布・デプロイすることが可能になります。

Phar::webPharメソッドは、PharファイルをWebサーバーのエントリポイントとして機能させるための設定です。このメソッドで指定したPhar内部のPHPファイルが、すべてのWebリクエストを処理する唯一のエントリポイントとなります。そのため、内部のスクリプトでは$_SERVER['REQUEST_URI']などを用いてURLに応じたルーティング処理を必ず実装する必要があります。サンプルコードはPHP組み込みサーバーでの動作確認を想定しており、本番環境で利用する際は、ApacheやNginxなどのWebサーバー設定でPharファイルへのリダイレクトルールを追加する必要がある点に注意してください。Pharアーカイブの安全な運用のため、作成後の改ざん防止策として署名機能の利用を検討するなど、セキュリティ対策を講じることが重要です。

関連コンテンツ

関連IT用語

関連プログラミング言語