こんにちは!チームのコード品質と開発スピードを限界まで引き上げるのが大好きな、君の専属の先輩エンジニアだよ。
今日はいよいよ、現代のPHP開発において避けて通れない、しかし多くの開発者が一度は頭を悩ませる「マルチPHP環境とComposerのスマートな連携術」について話をしよう。
「ローカルではPHP 8.3でバリバリ開発しているのに、クライアントの本番サーバーはまだPHP 8.1だからデプロイでエラーになった」
「Dockerコンテナの中と外でComposerの依存関係が競合して、Vendorディレクトリが爆発した」
……こんな絶望的なシチュエーション、君も経験したことがないかい?これをマスターすれば、日々の環境構築やバージョン起因のトラブルで無駄な時間を溶かすことが一切なくなる。胸を張って「自分のコードはどのPHP環境でも完璧に動く」と言えるようになるんだ。
さあ、骨太だけど誰よりも分かりやすい、最高の旅を始めようか!
—
1. なぜComposerの「platform設定」がマルチPHP環境の救世主なのか?
まずは、Composerというツールの本質を少しだけ深く理解しよう。
Composerは単なるライブラリのダウンローダーではない。「あなたのプロジェクトが要求するPHPのバージョンと、利用可能なPHPの機能(拡張モジュールなど)の整合性を数学的に検証するエンジン」なんだ。
通常、Composerは「今、自分の手元で動いているPHPのバージョン」を基準にして、インストールするパッケージのバージョンを決定する。
例えば、君のローカルPCにPHP 8.3が入っている状態で `composer install` を実行すると、Composerは「このプロジェクトはPHP 8.3の機能を使って動くんだな」と判断し、PHP 8.3以降を必須とする最新パッケージをガンガン持ってくる。
しかし、本番環境がPHP 8.1だったらどうなる?
「Fatal error: Uncaught Error: Call to undefined function…」という、エンジニアの夜を台無しにする恐怖のクラッシュが起きてしまう。
救世主:`config.platform` の力
ここで登場するのが、Composerの `composer.json` に設定できる `config.platform` だ。
これを使うと、「実際のローカル環境のPHPバージョンに関係なく、指定したPHPバージョン(例: 8.1.25)が動いていると仮定して依存関係を解決させろ」とComposerに命令できる。
これにより、手元は最新のPHP 8.3で快適にコーディングしつつ、依存関係の解決は厳格に本番のPHP 8.1基準で行う、という夢のようなマルチPHP運用が成立するんだ。
—
2. 実践:DockerとComposerを組み合わせた堅牢な開発環境の構築
では、理論をコードに落とし込もう。
今回は、Dockerを使ってローカルに複数のPHPバージョンを行き来できる環境を想定し、最も堅牢な `composer.json` の設計図を作ってみるよ。
ステップ1: `composer.json` の設計
プロジェクトのルートディレクトリにある `composer.json` を開いて(なければ `composer init` で作ってね)、以下のように `config` セクションを追記・調整しよう。
{
“name”: “developer/multi-php-app”,
“description”: “Composer multi-PHP environment mastery project”,
“type”: “project”,
“require”: {
“php”: “>=8.1”,
“monolog/monolog”: “^3.0”
},
“config”: {
/
重要: ここで本番環境のPHPバージョンを明示的にエミュレートする。
これにより、ローカルがPHP 8.3であっても、PHP 8.1で動く範囲のパッケージ選定を強制できる。
/
“platform”: {
“php”: “8.1.25”
},
/
OPTIMIZATION: パッケージのインストールを高速化するためのベストプラクティス
/
“preferred-install”: “dist”,
“sort-packages”: true
}
}
ステップ2: Docker環境でのComposer実行フロー
マルチPHP開発において、ホストOS(自分のPC)のPHP直接叩くのは御法度だ。なぜなら、プロジェクトによって必要なPHPのバージョンが違うからね。
Dockerコンテナ内のPHPとComposerをエイリアス(ショートカット)として利用するのがプロの常道だ。
例えば、プロジェクトのルートに以下のようなシェルスクリプト(`composer.sh` など)を用意しておくと、チーム全員が同じバージョンでComposerを叩けるようになる。
!/bin/bash
エラーが発生した時点でスクリプトを即座に停止する堅牢な設定
set -e
ホスト側のPHPではなく、Dockerコンテナ内の指定PHP(ここではPHP 8.1)のコンテナ経由でComposerを実行する
docker run –rm \
-v “$(pwd)”:/app \
-w /app \
–user “$(id -u):$(id g)” \
composer:2.6 \
“$@”
※このスクリプトを作っておけば、 `./composer.sh install` と叩くだけで、Docker内のComposerが動き、ホストの環境汚染を完全に防げるんだ。
—
3. 精度高い「Hello World」的動作確認で環境をテストする
環境が正しく構築できているか、実際にコードを書いてテストしてみよう。
ここでは、Monologという著名なログライブラリを使い、指定したPHPのバージョンエミュレーションが正しく機能しているかをコンソール出力で確認する。
1. 依存関係のインストール(実行ログ)
先ほど作成した `composer.json` に向かって、Docker経由(またはプラットフォーム設定を意識したローカル)でComposerを実行する。
$ composer install
実行時のComposerの思考プロセス(ログのイメージ)
> Loading composer repositories with package information
> Info from https://repo.packagist.org: # パッケージ情報をロード中
> Restricting packages listed in “config.platform” to “8.1.25” # ★ここがポイント!PHP 8.1.25としてパッケージを解決
> Installing dependencies from lock file
> Verifying lock file contents can be installed on current platform.
> Nothing to install, updating lock file
このように、`Restricting packages listed in “config.platform” to “8.1.25”` というログが出れば大成功!Composerは君の意図を完璧に理解している。
2. 動作確認スクリプトの作成
プロジェクト直下に `index.php` を作成し、以下のコードを記述してほしい。
pushHandler(new StreamHandler(‘php://stdout’, Level::Debug));
// 3. 動作確認用のメッセージを流す
$log->info(‘素晴らしい!ComposerのマルチPHPプラットフォーム設定は完璧に機能しています。’, [
‘runtime_php_version’ => PHP_VERSION, // 実際に実行しているPHPのバージョン
‘target_env’ => ‘Production Emulated (PHP 8.1.25)’
]);
3. 実行と結果
ターミナルからこのスクリプトをPHPで実行してみよう。
$ php index.php
【出力結果のイメージ】
[2023-10-27T12:00:00.123456+00:00] multi-php-test.INFO: 素晴らしい!ComposerのマルチPHPプラットフォーム設定は完璧に機能しています。 {“runtime_php_version”:”8.3.0″,”target_env”:”Production Emulated (PHP 8.1.25)”}
おめでとう!
注目してほしいのは、実行しているPHP自体のバージョンは `8.3.0` なのに、ComposerはPHP 8.1で動作する安全なパッケージの組み合わせをビルドしてくれているという点だ。
これにより、「ローカルの最新環境で開発・テストしつつ、本番の古いバージョンでも絶対に破綻しない」という、エンジニアにとって最高に心地よい開発環境が手に入ったことになる。
—
先輩からのアドバイス:毎日のコーディングを劇的に楽にするために
マルチPHP環境とComposerの `platform` 設定。一見すると地味なJSONの1行に思えるかもしれないけれど、これこそが「環境差異によるバグ」を根絶するための強力な防壁なんだ。
チーム開発でこれを導入すれば、「私のローカルでは動くのに、本番で落ちた」という不毛な議論は二度と起きなくなる。
ぜひ今日のプロジェクトから、`config.platform` を意識した設計を取り入れてみてほしい。あなたのエンジニアリングライフが、もっとスマートで快適になるはずだからね!