問題の概要PHPアプリケーションを単一の実行可能な .phar ファイルにまとめようとしています。ビルドスクリプトを実行し、完成したパッケージを期待していますが、プロセスが即座にクラッシュします。ファイルの代わりに、Phar->__construct 例外で終わる10行のスタックトレースが表示されます。
Fatal error: Uncaught UnexpectedValueException: creating archive "project.phar" is disabled by the php.ini setting phar.readonly in /path/to/build-script.php:10
このエラーは、ローカル開発中や、CLIツールの配布を自動化するCI/CDパイプライン内で特によく発生します。BoxなどのツールやカスタムのPhar作成スクリプトを使用する際によくある障害です。
なぜPHPはPharの作成をブロックするのかphar.readonly 設定は、組み込みの安全スイッチです。PHPはデフォルトでこれを 1 (On) に設定しており、スクリプトが誤って、あるいは悪意を持ってPharファイルを作成するのを防いでいます。この保護機能は、ハッカーがPharアーカイブ内に隠された悪意のあるコードを実行しようとする「Pharデシリアライゼーション」攻撃を阻止するのに役立ちます。
注意点は、スクリプト内で ini_set('phar.readonly', 0); を使ってオフにすることはできないということです。これは高度なセキュリティ設定であるため、スクリプトの実行が開始された後に変更しようとしても、PHPはそれを無視します。エンジンが完全に初期化される前に無効化する必要があります。
解決策1:コマンドラインのオーバーライドを使用する(推奨)アーカイブをたまにしかビルドしないのであれば、グローバルなシステム設定を変更しないでください。最も安全な方法は、実行する特定のコマンドに対してのみ制限を無効にすることです。これにより、ビルドスクリプトを実行しつつ、システムのセキュリティを維持できます。
-d フラグを使用して、実行時に設定を変更します:
php -d phar.readonly=0 build.phar.php
各パーツの役割は以下の通りです:
-d: この1回の実行に対してカスタム設定を定義するようPHPに指示します。-phar.readonly=0: 読み取り専用モードを「Off」に切り替えます。-build.phar.php: 特定のパッケージ化スクリプトの名前です。## 解決策2:php.iniを更新する(永続的な修正)専用のビルドサーバーや、毎日Pharをビルドするローカルマシンでは、永続的な変更を行うことで時間を節約できます。まず、正しい設定ファイルを見つける必要があります。
ステップ1:CLIの設定ファイルを特定するターミナルが実際に使用しているファイルを確認するために、次のコマンドを実行します:
php --ini
Loaded Configuration File のパスを探します。Ubuntuの場合、通常は /etc/php/8.2/cli/php.ini のようになっています。
ステップ2:ファイルを編集するsudo と、NanoやVimなどのお好みのエディタを使用してそのファイルを開きます:
sudo nano /etc/php/8.2/cli/php.ini
ステップ3:値を変更する[Phar] セクションを探します。行を次のように変更します:
phar.readonly = Off
保存して終了します。この変更はPHP CLIにのみ影響するため、ApacheやNginxを再起動する必要はありません。
解決策3:DockerおよびCI/CDでの回避策Dockerコンテナ内やGitHub ActionでPharをビルドする場合、ファイルを手動で編集することはできません。スクリプトによるアプローチが必要です。
Dockerfileを使用する場合イメージのビルドフェーズ中に設定を注入するために、Dockerfileに次の行を追加します:
RUN echo "phar.readonly=0" >> /usr/local/etc/php/conf.d/docker-php-ext-phar.ini
GitHub Actionsを使用する場合人気のある shivammathur/setup-php アクションを使用している場合は、ワークフローのYAMLファイルで直接設定を渡すことができます:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
ini-values: phar.readonly=0
修正のテストターミナルで次のワンライナーを実行して、設定が有効であることを確認します:
php -r "echo 'Readonly is: ' . ini_get('phar.readonly');"
もし Readonly is: 0 と返されれば、準備完了です。また、次の最小限のテストスクリプトを実行して、Phar オブジェクトがクラッシュせずに初期化されることを確認できます:
<?php
try {
$p = new Phar('test.phar');
echo "成功: Pharアーカイブが初期化されました。";
} catch (Exception $e) {
echo "エラー: " . $e->getMessage();
}

