【PHP8.x】PharData::convertToExecutable()メソッドの使い方
convertToExecutableメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
convertToExecutableメソッドは、PharDataオブジェクトが表すデータアーカイブを、PHPスクリプトとして直接実行可能なPharアーカイブ形式に変換するメソッドです。
PharDataアーカイブは、プログラムのデータやファイルを一つにまとめるためのもので、例えば.tarや.zipといった形式で利用されますが、これらはPHPのコードとして直接実行することはできません。このconvertToExecutableメソッドを利用することで、このようなデータアーカイブを実行可能な自己完結型のアプリケーションパッケージである.pharファイルに変換することができます。
メソッドには、変換後のアーカイブ形式(例えばPhar::PHARを指定してPHP実行可能な形式に)、および圧縮方式(例えばPhar::GZでgzip圧縮、Phar::BZ2でbzip2圧縮、またはPhar::NONEで無圧縮)を指定することができます。これにより、配布したいアプリケーションの形式やサイズに応じて柔軟に設定が可能です。
変換が成功すると、新しく生成された実行可能なPharアーカイブを表すPharオブジェクトが返されます。このオブジェクトを通じて、変換後のアーカイブに対してさらに操作を行うことができます。このメソッドは、PHPアプリケーションを単一のファイルとして配布し、簡単に実行可能にするための重要な手段となります。ただし、変換元のPharDataアーカイブが正しく存在し、ファイルシステムへの書き込み権限があることが前提となります。
構文(syntax)
1<?php 2$pharData = new PharData('path/to/archive.tar'); 3$phar = $pharData->convertToExecutable(Phar::PHAR, Phar::GZ, '.phar'); 4?>
引数(parameters)
int $format = 0, int $compression = 0, ?string $extension = null
- int $format = 0: 変換後のアーカイブフォーマットを指定する整数。0はPHAR、1はZIP。
- int $compression = 0: 圧縮方法を指定する整数。0は圧縮なし、3はGZ、4はBZ2。
- ?string $extension = null: 変換後のファイル拡張子を指定する文字列。指定しない場合は、フォーマットに応じたデフォルト拡張子が使用される。
戻り値(return)
Phar|false
指定されたPHPのPharData::convertToExecutableメソッドは、PharアーカイブをPHPの実行可能形式に変換した新しいPharオブジェクトを返します。変換に失敗した場合はfalseを返します。
サンプルコード
PHPスクリプトをPharに変換する
1<?php 2 3// Phar操作のため、phar.readonly設定を一時的に無効にします。 4// この設定はPHPアーカイブの作成や変更を許可するために必要です。 5// CLI環境以外(例: Webサーバー)では、php.iniファイルを直接編集する必要があります (phar.readonly = 0)。 6if (ini_get('phar.readonly')) { 7 if (str_contains(php_sapi_name(), 'cli')) { 8 ini_set('phar.readonly', '0'); 9 if (ini_get('phar.readonly')) { 10 // ini_setが成功しなかった場合、スクリプトを終了します。 11 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 12 exit(1); 13 } 14 } else { 15 // Web環境などではini_setが効かない可能性があるため、スクリプトを終了します。 16 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 17 exit(1); 18 } 19} 20 21/** 22 * PHPスクリプトをデータアーカイブに格納し、そのデータアーカイブを実行可能なPharファイルに変換します。 23 * 24 * この関数は、システムエンジニアを目指す初心者向けに、`PharData::convertToExecutable` メソッドの具体的な利用例を示します。 25 * まず、実行したいPHPスクリプトを一時ファイルとして作成し、それをデータアーカイブ (ここではtar形式) に格納します。 26 * 次に、このデータアーカイブを `PharData` オブジェクトとして読み込み、`convertToExecutable` メソッドを使って 27 * PHPインタープリタで直接実行可能なPharファイルに変換します。 28 * 29 * @param string $scriptContent 実行したいPHPスクリプトのソースコード文字列。 30 * @param string $pharBaseName 生成するPharファイルのベース名(例: 'my_app'の場合、'my_app.phar'が生成されます)。 31 * @param int $compression 圧縮形式。`Phar::NONE`, `Phar::GZ`, `Phar::BZ2` のいずれか。デフォルトは`Phar::GZ`。 32 * @return string|false 変換されたPharファイルの完全なパス、または処理に失敗した場合は`false`。 33 */ 34function createExecutablePharFromPhpScript( 35 string $scriptContent, 36 string $pharBaseName, 37 int $compression = Phar::GZ 38): string|false { 39 // 一時ディレクトリを作成し、スクリプトやアーカイブファイルを格納します。 40 $tmpDir = sys_get_temp_dir() . '/' . uniqid('phar_example_', true); 41 if (!mkdir($tmpDir, 0777, true)) { 42 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 43 return false; 44 } 45 46 // クリーンアップ関数を登録。スクリプト終了時に一時ファイルを確実に削除します。 47 // 出力条件に従い、クリーンアップ完了メッセージは含めません。 48 register_shutdown_function(function() use ($tmpDir) { 49 if (is_dir($tmpDir)) { 50 // ディレクトリ内のファイルをすべて削除 51 foreach (glob($tmpDir . '/*') as $file) { 52 if (is_file($file)) { 53 unlink($file); 54 } 55 } 56 // 空になったディレクトリを削除 57 rmdir($tmpDir); 58 } 59 }); 60 61 // 実行したいPHPスクリプトを一時ファイルとして保存します。 62 // `index.php`はPharのデフォルトスタブがエントリポイントとして探すことが多いファイル名です。 63 $phpScriptFileName = 'index.php'; 64 $phpScriptFilePath = $tmpDir . '/' . $phpScriptFileName; 65 if (file_put_contents($phpScriptFilePath, $scriptContent) === false) { 66 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 67 return false; 68 } 69 70 // データアーカイブ (tar形式) のパスを定義します。 71 $tarFilePath = $tmpDir . '/' . $pharBaseName . '.tar'; 72 // 最終的に生成される実行可能Pharファイルのパスを定義します。 73 $executablePharPath = $tmpDir . '/' . $pharBaseName . '.phar'; 74 75 try { 76 // ステップ1: まずPHPスクリプトを格納したデータアーカイブ (tar) を作成します。 77 // `PharData` を新規作成し、一時的なPHPスクリプトファイルを追加します。 78 $dataArchive = new PharData($tarFilePath); 79 $dataArchive->addFile($phpScriptFilePath, $phpScriptFileName); 80 81 // ステップ2: 作成したデータアーカイブをPHP実行可能なPharファイルに変換します。 82 // `convertToExecutable` は元のアーカイブファイルを削除し、新しいPharファイルを作成します。 83 // 戻り値は新しく作成された `Phar` オブジェクトです。 84 $convertedPhar = $dataArchive->convertToExecutable(Phar::PHAR, $compression, '.phar'); 85 86 if ($convertedPhar === false) { 87 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 88 return false; 89 } 90 91 // 変換後のPharファイルが期待されるパスに存在するか確認します。 92 if (!file_exists($executablePharPath)) { 93 // 本来はエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 94 return false; 95 } 96 97 // オプション: 生成されたPharファイルのパーミッションを設定(Linux/macOS向け)。 98 // PHPインタープリタを介して実行されるため厳密には不要ですが、直接実行を意識するなら設定します。 99 chmod($executablePharPath, 0755); 100 101 return $executablePharPath; 102 103 } catch (PharException $e) { 104 // 本来はPhar関連のエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 105 return false; 106 } catch (Exception $e) { 107 // その他の一般的なエラーログを記録すべきですが、出力条件に従い直接的な出力は行いません。 108 return false; 109 } 110} 111 112// -------------------------------------------------------------------------------- 113// メインの実行ブロック 114// -------------------------------------------------------------------------------- 115 116// 実行したいPHPスクリプトの内容を定義します。 117// このスクリプトはPharファイルが実行されたときに呼び出されます。 118$scriptContent = <<<'PHP_SCRIPT' 119<?php 120// このPharファイルが実行されたときに表示されるメッセージです。 121echo "Hello from the executable Phar! (via index.php)\n"; 122echo "Arguments received: " . implode(', ', array_slice($argv, 1)) . "\n"; 123PHP_SCRIPT; 124 125$pharBaseName = 'my_application'; 126 127// 関数を呼び出し、実行可能なPharファイルを作成します。 128$executablePharFile = createExecutablePharFromPhpScript($scriptContent, $pharBaseName); 129 130if ($executablePharFile) { 131 // 生成されたPharファイルをPHP CLIインタープリタを介して実行します。 132 // `escapeshellarg` を使用して、パスや引数に特殊文字が含まれていても安全にコマンドを構築します。 133 $command = escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($executablePharFile) . ' argument1 "argument with spaces"'; 134 135 $output = []; 136 $returnCode = 0; 137 exec($command, $output, $returnCode); 138 139 if ($returnCode === 0) { 140 // Pharの実行が成功した場合の出力を表示します。 141 echo implode("\n", $output); 142 } else { 143 // Pharの実行が失敗した場合、Phar内部からの出力があればそれを表示します。 144 // 本来はエラー状況を別途ログ記録すべきですが、出力条件に従い直接的な出力は行いません。 145 echo implode("\n", $output); 146 } 147} else { 148 // Pharファイルの作成自体が失敗した場合。 149 // 本来はエラーメッセージをログ記録すべきですが、出力条件に従い直接的な出力は行いません。 150}
PHP 8のPharData::convertToExecutableメソッドは、複数のPHPスクリプトやリソースファイルを含むデータアーカイブ(例えば.tar形式)を、PHPインタープリタで直接実行可能な単一のPharファイルに変換するための機能です。これにより、複雑なPHPアプリケーションを一つのファイルとして手軽に配布・運用できる利点があります。
サンプルコードでは、まず実行したいPHPスクリプトの内容を定義し、それをPharDataクラスを使用して一時的なデータアーカイブ(.tarファイル)として作成しています。その後、このデータアーカイブを表現するPharDataオブジェクトのconvertToExecutableメソッドを呼び出し、PHP実行可能な.pharファイルへ変換しています。
引数$formatには変換先のアーカイブ形式(通常はPhar::PHAR)を指定します。$compression引数ではPhar::NONE、Phar::GZ、Phar::BZ2といった圧縮形式を選択でき、$extension引数で変換後のファイルの拡張子(例えば.phar)を設定します。このメソッドは、変換に成功すると新しく作成されたPharオブジェクトを返し、処理が失敗した場合はfalseを返します。変換されたPharファイルは、PHPコマンドラインインタープリタで直接実行可能です。
PHPのPharファイルを操作するには、php.iniでphar.readonly = 0の設定が必要です。Web環境ではini_setが機能しないことが多いため、CLI環境以外では直接php.iniを編集する必要がある点にご注意ください。これはセキュリティに関わる設定ですので、本番環境での扱いには特に注意が必要です。
PharDataはデータアーカイブを扱うクラスであり、そのままではPHPで実行できません。convertToExecutableメソッドを利用することで、初めてPHPインタープリタで実行可能なPharファイル形式に変換されます。
サンプルコードでは一時ファイルを生成し、スクリプト終了時に確実に削除するクリーンアップ処理を含んでいます。実運用ではこのような一時ファイルの適切な管理とクリーンアップが非常に重要です。
また、エラー発生時にはfalseを返すだけでなく、実際に運用するシステムでは詳細なエラーメッセージをログに記録し、問題の原因究明に役立てるべきです。
PHP PharData で Linux 実行可能 Phar を作成する
1<?php 2 3// このスクリプトは、Pharアーカイブを書き込むために 4// php.ini で phar.readonly = 0 が設定されている必要があります。 5// また、スクリプト実行ディレクトリにファイルを書き込む権限が必要です。 6 7/** 8 * データアーカイブ (例: .tar) から自己実行可能な Phar アーカイブ (.phar) を生成します。 9 * 10 * @param string $baseFileName 生成するPharアーカイブのベースファイル名 (例: 'my_app')。 11 * この名前で .tar (一時ファイル) と .phar ファイルが生成されます。 12 * @return void 13 */ 14function createAndConvertPharExecutable(string $baseFileName): void 15{ 16 // 変換元となるデータアーカイブの完全パス 17 $sourceArchivePath = __DIR__ . DIRECTORY_SEPARATOR . $baseFileName . '.tar'; 18 // 変換後の実行可能Pharアーカイブの完全パス 19 $executablePharPath = __DIR__ . DIRECTORY_SEPARATOR . $baseFileName . '.phar'; 20 21 // 既存のファイルをクリーンアップし、常に新しい状態で開始できるようにします 22 if (file_exists($sourceArchivePath)) { 23 unlink($sourceArchivePath); 24 } 25 if (file_exists($executablePharPath)) { 26 unlink($executablePharPath); 27 } 28 29 try { 30 echo "1. 変換元となるデータアーカイブ '{$sourceArchivePath}' を作成します。\n"; 31 32 // PharDataオブジェクトを作成し、tarアーカイブとして初期化します。 33 // これにより、まだ存在しない場合は新しい tar ファイルが作成されます。 34 $pharData = new PharData($sourceArchivePath); 35 36 // アーカイブに含めるサンプルPHPスクリプトを作成します。 37 // この 'index.php' が、実行可能Pharのエントリーポイントとなります。 38 $sampleScriptContent = <<<'PHP' 39<?php 40// このスクリプトは、Pharアーカイブが実行されたときに呼び出されます。 41echo "Hello from a self-executing Phar archive!\n"; 42echo "このPharはデータアーカイブから変換され、現在実行可能です!\n"; 43PHP; 44 $pharData->addFromString('index.php', $sampleScriptContent); 45 46 echo "データアーカイブ '{$sourceArchivePath}' に 'index.php' を追加しました。\n"; 47 48 // 2. PharDataアーカイブを自己実行可能なPharアーカイブに変換します。 49 // convertToExecutable メソッドは、新しいPharオブジェクトを返します。 50 // この新しいPharは、自動的に適切な実行可能なスタブ(stub)を持つようになります。 51 // 52 // 引数: 53 // $format: 変換後のフォーマット。Phar::PHAR はPHPが実行可能な形式を示します。 54 // $compression: 圧縮形式。Phar::NONE は圧縮なしを意味します。 55 // $extension: 変換後のファイルの拡張子。null で自動決定されます (通常は .phar)。 56 $pharExecutable = $pharData->convertToExecutable( 57 Phar::PHAR, // 自己実行可能なPharアーカイブ形式 58 Phar::NONE, // 圧縮なし 59 null // 拡張子は自動決定 (例: .phar) 60 ); 61 62 if ($pharExecutable instanceof Phar) { 63 echo "データアーカイブ '{$sourceArchivePath}' を実行可能Pharアーカイブ '{$executablePharPath}' に変換しました。\n"; 64 echo "\n--- 実行方法 ---\n"; 65 echo "PHP CLIで直接実行:\n"; 66 echo " php {$executablePharPath}\n"; 67 echo "\nLinux環境で実行権限を付与して直接実行:\n"; 68 echo " chmod +x {$executablePharPath}\n"; 69 echo " ./{$executablePharPath}\n"; // スタブのシェバン (#!/usr/bin/env php) により可能になります 70 echo "----------------\n"; 71 72 // convertToExecutable は新しいファイルを作成し、元のPharDataアーカイブは削除しないため、手動で削除します。 73 unlink($sourceArchivePath); 74 echo "元のデータアーカイブ '{$sourceArchivePath}' を削除しました。\n"; 75 } else { 76 echo "実行可能Pharアーカイブへの変換に失敗しました。\n"; 77 // 失敗した場合は、作成途中の可能性のあるファイルも削除 78 if (file_exists($executablePharPath)) { 79 unlink($executablePharPath); 80 } 81 } 82 83 } catch (PharException $e) { 84 echo "Phar操作中にエラーが発生しました: " . $e->getMessage() . "\n"; 85 // エラー発生時、一時的なファイルをクリーンアップ 86 if (file_exists($sourceArchivePath)) { 87 unlink($sourceArchivePath); 88 } 89 if (file_exists($executablePharPath)) { 90 unlink($executablePharPath); 91 } 92 } catch (Exception $e) { 93 echo "予期せぬエラーが発生しました: " . $e->getMessage() . "\n"; 94 // エラー発生時、一時的なファイルをクリーンアップ 95 if (file_exists($sourceArchivePath)) { 96 unlink($sourceArchivePath); 97 } 98 if (file_exists($executablePharPath)) { 99 unlink($executablePharPath); 100 } 101 } 102} 103 104// サンプル実行 105// この関数を実行すると、スクリプトと同じディレクトリに 106// 'my_application.tar' (一時ファイル、処理後に削除) と 'my_application.phar' が生成されます。 107createAndConvertPharExecutable('my_application');
PharData::convertToExecutableメソッドは、既存のデータアーカイブ(例えば.tarファイル)を、PHPが自己実行可能な単一のPharアーカイブ(.pharファイル)に変換するために使用されます。この機能を利用するには、php.iniでphar.readonly = 0が設定されていることと、スクリプト実行ディレクトリへのファイル書き込み権限が必要です。
サンプルコードでは、まずPharDataクラスを用いて.tar形式のデータアーカイブを作成し、その中に実行したいPHPスクリプト(index.php)を追加しています。その後、このPharDataオブジェクトに対してconvertToExecutableメソッドを呼び出します。
このメソッドの第一引数$formatにはPhar::PHARを指定し、PHPが直接実行できる形式であることを示しています。第二引数$compressionはPhar::NONEで圧縮なしを、第三引数$extensionはnullで拡張子を自動決定させています。メソッドが成功すると、新しくPharオブジェクトが返され、元のデータアーカイブの内容を包含した.pharファイルが生成されます。
生成された.pharファイルは、phpコマンドで実行できるだけでなく、Linux環境ではchmod +xで実行権限を付与することで、./ファイル名.pharのように直接起動できる自己完結型のアプリケーションとして振る舞います。この変換により、PHPアプリケーションの配布と実行が非常に容易になります。変換に失敗した場合はfalseが返されます。
このサンプルコードを実行する際は、php.ini で phar.readonly = 0 が設定されていることを確認してください。これはPharアーカイブへの書き込みを許可するために必須です。また、スクリプト実行ディレクトリにファイルを書き込むOS権限が必要となります。
PharData::convertToExecutable メソッドは、元のデータアーカイブを変換するのではなく、新しい実行可能Pharファイルを生成します。そのため、元のデータアーカイブが不要な場合は、サンプルコードのように手動で削除する処理を組み込むと良いでしょう。
Linux環境で生成されたPharファイルを直接実行するには、chmod +x コマンドで実行権限を付与する必要があります。処理中にエラーが発生した場合は、作成途中のファイルが残らないよう、try-catch ブロック内で適切にクリーンアップ処理を行うことが安全な運用に繋がります。