結論から書くと、composer update が怖いのは、実行すると何がどれだけ変わるのかが分からない からです。対策は3つです。今の状態を composer.lock で固定すること、更新を小さく分けること、1回ごとに確認して戻れる地点を作ることです。引数なしの composer update を一度に実行するのは、最後の手段にします。
この記事のコマンドは、Composer の 公式ドキュメントのコマンド一覧に載っているものだけを使っています。
composer update が怖い理由
まず、install と update の違いを押さえます。公式の説明では、composer install は composer.lock があれば、そこに書かれた正確なバージョンを入れます。一方、composer update は依存関係を解決し直し、新しいバージョンを composer.lock に書き込みます。つまり引数なしの update は、composer.json の範囲内で、すべてのパッケージを一度に上げる 操作です。
これが古いシステムで怖い操作になるのは、次のような事情が重なるからです。
composer.lockがリポジトリに無い、または本番のvendorと一致していない。今の状態を再現できないvendorの中のファイルを直接書き換えている。パッケージが入れ替わったときや、新しい環境で入れ直したときに修正が消える- 手元の PHP と本番の PHP のバージョンが違う。手元で解決したバージョンが、本番の PHP では動かないことがある
- テストが無く、何が壊れたかに気づく手段が無い
手順1: 今の状態を固定する
最初に、今動いている状態を記録して、いつでも戻れるようにします。
- 本番の
vendorとcomposer.lockを確認する。 リポジトリと本番で中身が違う場合は、本番を正としてコピーを取ります。vendorの中を書き換えていないかも、ここで差分を取って確かめます。 composer.lockをコミットする。 公式も、composer.lock をバージョン管理に含めるよう勧めています。これが戻る地点になります。- 検証環境で
composer installして動くか確かめる。 ここで動かなければ、更新の前にその原因を解決します。 - 本番の PHP のバージョンを設定する。 設定の platform に本番の PHP のバージョンを書くと、それより新しい PHP を必要とするパッケージが入らなくなります。
# 本番の PHP が 8.2 の場合の例
composer config platform.php 8.2
公式ドキュメントには、platform を設定すると実際の環境との違いが検査されなくなるため、デプロイの手順で check-platform-reqs も実行するよう書かれています。本番で composer check-platform-reqs を実行すると、本番の PHP と拡張モジュールが、入っているパッケージの要件を満たしているかを確認できます。
手順2: 何が上がるかを先に見る
更新する前に、候補と影響を一覧にします。
composer outdated --direct # 直接使っているパッケージの更新候補
composer audit # 既知の脆弱性と、保守が止まったパッケージ
composer update --dry-run # 実際には何も変えずに、変わる内容を表示する
composer why-not vendor/package 3.0 # 3.0 に上げられない理由
composer outdated の表示は色で分かれます。赤は互換性を保ったまま上げられる更新、黄色は互換性を壊す変更を含む更新です。最初に扱うのは、audit で脆弱性が見つかったものと、赤のものです。
手順3: 小さく分けて上げる
更新は、影響が小さいものから順に、まとまりごとに分けて行います。
- 脆弱性があるパッケージ。 パッケージ名を指定して、そのパッケージだけを上げます。
- パッチの更新。
--patch-onlyを付けると、パッチバージョンの更新だけに絞れます。 - マイナーの更新。 1つずつ、または関係するまとまりごとに上げます。
- メジャーの更新。
composer.jsonの制約を書き換える必要があります。別の作業として、パッケージの変更履歴やアップグレードの案内を読んでから行います。
composer update vendor/package --with-dependencies # 指定したものと、その依存だけを上げる
composer update --patch-only # パッチの更新だけ
composer update vendor/package --minimal-changes # 必要な変更だけにとどめる
--with-dependencies(-w)は、指定したパッケージが依存しているパッケージもあわせて上げます。ただし composer.json に直接書かれているものは除きます。それも含めたい場合は --with-all-dependencies(-W)です。--minimal-changes を付けると、指定したパッケージ以外は、今のバージョンのままでいられないものだけが更新されます。どれも update の説明に載っています。
1回の更新が終わるたびに、composer.json と composer.lock を一緒にコミットします。コミットのメッセージには、上げたパッケージとバージョンを書いておきます。問題が出たときに、どの更新が原因かをすぐに絞り込めます。
手順4: 確認して、本番に反映する
1回ごとの確認は次のとおりです。
git diff composer.lockで、意図したパッケージだけが変わっているかを見る- テストがあれば実行する。無ければ、止まると困る機能の確認項目を実行する
- エラーログに、新しいエラーや非推奨の警告が出ていないかを見る
テストが無い場合は、止まると困る機能の確認を手順書にしておくだけでも、確認の漏れは減ります。毎回同じ手順で確認できることが大切です。
本番には、本番で composer update を実行せず、コミットした composer.lock を使って反映します。本番で Composer を実行できる環境なら、composer install --no-dev です(--no-dev は開発用のパッケージを入れません)。レンタルサーバーなどで Composer を実行できない場合は、本番と同じバージョンの PHP で作った vendor を転送します。
戻すときは、前のコミットの composer.json と composer.lock に戻して composer install を実行します。
やらないほうがよいこと
- 本番で
composer updateを実行する。 何が入るかを確かめないまま、本番の依存を変えることになります。 --ignore-platform-reqsを常用する。 公式の説明どおり、手元の環境が要件を満たしていなくても強制的に入れるオプションです。本番の PHP で動かないパッケージが入る原因になります。composer.lockを消して作り直す。 すべてのパッケージが一度に変わり、引数なしのupdateと同じことになります。vendorの中を直接直す。 そのパッケージを更新したときや、新しい環境で入れ直したときに消えます。どうしても必要な修正は、自分のコードの側に移します。
依存の更新は、Laravel のバージョンアップの前段の作業でもあります。全体の流れは「Laravel バージョンアップの手順と、実際に詰まるポイント」を、本番と vendor の差分の確かめ方は「前任者がいない PHP システムの引継ぎ調査、最初の1週間でやること」をご覧ください。
h-system でできること
h-system では、依存パッケージの更新が止まった PHP・Laravel のシステムについて、今の状態の確認から、脆弱性のあるパッケージの更新、メジャー更新の計画までを開発者本人がお引き受けしています。「composer update を実行してよいか分からない」という段階で、現状を調べるだけのご依頼も可能です。初回のご相談と概算のお見積りは無料で、詳細な調査は有償です。範囲と費用は着手前にご案内します。