2026年9月8日
2026年9月8日
composer.jsonとcomposer.lockの管理方法:installとupdateの使い分けとロックファイルの扱い
composer.json は「どの範囲のバージョンを許可するか」を書く設計図で、composer.lock は「実際にどのバージョンを入れたか」を記録した確定版です。この 2 つの役割を区別し、composer install と composer update を正しく使い分ければ、開発環境・CI・本番で同じ依存関係を再現できます。この記事では、WordPress のサイトやテーマ・プラグイン開発を例に、ロックファイルをコミットするかどうかの判断、更新の手順、マージ時の衝突の解消方法までを説明します。
composer.jsonとcomposer.lockの役割
composer.json には、必要なパッケージとバージョンの制約を書きます。
{
"name": "example/my-site",
"require": {
"php": ">=8.1",
"composer/installers": "^2.0",
"monolog/monolog": "^3.0"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.7",
"phpunit/phpunit": "^10.5"
},
"config": {
"platform": {
"php": "8.1.0"
},
"allow-plugins": {
"composer/installers": true
}
}
}
^3.0 は「3.0 以上 4.0 未満」を表す制約で、互換性を保つ範囲での更新を許可します。~3.1 は「3.1 以上 4.0 未満」、~3.1.0 は「3.1.0 以上 3.2 未満」と、最後に書いた桁の手前までを固定する意味になります。
一方 composer.lock には、制約を満たすバージョンの中から実際に選ばれたもの(依存の依存も含む)が、正確なバージョンとダウンロード元とともに記録されます。composer.json の内容から計算された content-hash も含まれていて、両者が食い違うと Composer が警告を出します。
composer.lock は Composer が自動で書き換えるファイルなので、手で編集してはいけません。
installとupdateの違い
- **
composer install**:composer.lockがあれば、そこに書かれたバージョンをそのまま入れます。ロックファイルは変わりません。CI や本番のデプロイ、他の人がリポジトリを取得したときに使うのはこちらです。 - **
composer update**:composer.jsonの制約の範囲で新しいバージョンを探し、入れ直してcomposer.lockを書き換えます。依存関係を意図して更新したいときだけ使います。
「とりあえず composer update」を本番サーバーで実行すると、テストしていないバージョンが入る恐れがあります。本番では composer install を使い、更新は開発環境で行ってテストした後、ロックファイルの変更をコミットして反映する、という流れが基本です。
更新は対象を絞る
引数なしの composer update はすべてのパッケージを更新するため、変更点の確認が難しくなります。特定のパッケージだけ更新するときは名前を指定します。
composer update monolog/monolog --with-dependencies
composer outdated --direct
--with-dependencies は、指定したパッケージが依存しているパッケージも必要に応じて一緒に更新するオプションです。composer outdated --direct を使うと、composer.json に直接書いたパッケージのうち新しいバージョンがあるものを一覧できるので、何を更新すべきか判断する材料になります。
パッケージを追加するときは composer require ベンダー名/パッケージ名、開発用なら composer require --dev ... を使います。これらは composer.json と composer.lock の両方を更新します。
composer.lockをコミットするかどうか
判断の基準は、そのリポジトリが「最終的に動かすもの」か「他から使われる部品」かです。
- サイト本体(Bedrock のような構成や、Composer でプラグインを管理するサイト): コミットします。本番と開発で同じバージョンを再現するためにロックファイルが欠かせません。
- 配布するプラグインやテーマ: コミットするのが一般的です。CI でのテストや配布用 ZIP のビルドで同じバージョンを使えるようにするためです。
- Packagist で公開する PHP ライブラリ: ライブラリを利用する側は、ライブラリの
composer.lockを参照しません。コミットしてもしなくても利用者には影響しないため、プロジェクトの方針で決めます。
vendor ディレクトリは .gitignore に入れ、リポジトリには含めないのが原則です。composer.lock があれば composer install でいつでも同じ内容を再現できます。
PHPのバージョンを固定する
Composer は、既定ではコマンドを実行した環境の PHP バージョンを前提に依存関係を選びます。開発環境が PHP 8.3、本番が PHP 8.1 の場合、開発環境で composer update すると PHP 8.2 以上を要求するバージョンが選ばれ、本番で動かなくなることがあります。
これを防ぐのが、例に含めた config.platform.php です。本番の PHP バージョンを書いておくと、手元の PHP が新しくても、そのバージョンで動くパッケージだけが選ばれます。本番の PHP を上げたときは、この値も合わせて更新します。
デプロイ先で拡張モジュールや PHP のバージョンが要件を満たしているかは、composer check-platform-reqs で確認できます。
本番向けのインストール
本番やデプロイ用のビルドでは、次のように実行します。
composer install --no-dev --optimize-autoloader --no-interaction
--no-dev で require-dev のパッケージを除外し、--optimize-autoloader でクラスの読み込みを高速化する設定を生成します。--no-interaction は確認の入力を求めないようにするオプションで、CI や自動デプロイで使います。
マージで composer.lock が衝突したとき
2 つのブランチがそれぞれパッケージを追加・更新すると、composer.lock でマージの衝突が起きます。content-hash を含む自動生成のファイルなので、テキストとして手で衝突を解消するのは避けます。次の手順で作り直すのが安全です。
composer.jsonの衝突を先に解消し、両方のブランチで追加・変更された内容を反映させます。composer.lockは、マージ先(たとえば main)の版を採用します。- 自分のブランチで行った変更を、改めて
composer update ベンダー名/パッケージ名やcomposer requireで適用し直します。 composer validateでファイルの整合性を確認し、テストを実行してからコミットします。
git checkout --theirs composer.lock # 状況によって --ours / --theirs は逆になる
composer update monolog/monolog --with-dependencies
composer validate
git checkout --ours と --theirs が指す側は、merge と rebase で逆になります。どちらがマージ先の版なのかを git status や差分で確認してから実行してください。
composer.json の変更がなく、content-hash の不一致の警告だけを解消したい場合は、composer update --lock でロックファイルのハッシュを更新できます。
脆弱性と定期的な更新
composer audit を実行すると、composer.lock に記録されたパッケージに既知の脆弱性がないかを確認できます(Composer 2.4 以降で利用できます。2026年10月現在)。CI に組み込んでおけば、脆弱性のあるバージョンが入ったまま気付かない状態を防げます。
更新を手作業だけに頼ると、つい後回しになりがちです。GitHub の Dependabot などを使うと、composer.json と composer.lock の更新をプルリクエストとして自動で作らせ、CI のテスト結果を見てから取り込めます。
WordPressのプラグイン開発での注意
複数のプラグインが同じライブラリの異なるバージョンを vendor に同梱していると、先に読み込まれた方のクラスが使われ、もう一方のプラグインが動かなくなることがあります。配布するプラグインで外部ライブラリを使う場合は、PHP-Scoper や Strauss などの名前空間を書き換えるツールで衝突を避ける方法が知られています。導入の手順はツールごとに異なるため、各ツールのドキュメントを確認してください。
また、Composer 2.2 以降では、パッケージに含まれる Composer プラグインを実行するかどうかを allow-plugins で明示する必要があります。composer/installers のように信頼できるものだけを許可し、知らないプラグインの実行を求められたら中身を確認してから判断します。
まとめ
composer.jsonは許可するバージョンの範囲、composer.lockは実際に入れたバージョンの記録。ロックファイルは手で編集しない。- 本番や CI では
composer install、意図して更新するときだけ開発環境でcomposer updateを対象を絞って使う。 - サイトや配布物のリポジトリではロックファイルをコミットし、
vendorはコミットしない。 config.platform.phpで本番の PHP バージョンに合わせて依存関係を選ばせる。- ロックファイルの衝突は手で直さず、マージ先の版を採用してから変更を適用し直し、
composer validateとテストで確認する。