- 何も変更していないのに動かなくなることは本当に起きる
- その日何が起きたのか
- 実際に起きていたこと
- 間接依存が最も危険
- なぜinstallでは起きないのか
- よくある誤解:updateは安全なメンテナンスではない
- 実際の復旧手順
- なぜPHPでこの問題が目立つのか
- 注意点:本番環境でupdateを実行しない
- まとめ:壊れたのはプロジェクトの前提だった
何も変更していないのに動かなくなることは本当に起きる
ある日、特にコードを触っていないのにアプリケーションが動かなくなりました。
原因はシンプルです。composer updateを実行しただけでした。
冗談のようですが、PHP開発では珍しい話ではありません。
そして重要なのは、これはComposerのバグではないという点です。
結論から言うと、composer updateは「ライブラリを更新するコマンド」ではなく、
依存関係を再計算するコマンドです。
ここを誤解すると、同じことが何度でも起きます。
その日何が起きたのか
軽い気持ちで実行したコマンド
きっかけはよくあるものです。
セキュリティ修正の案内が来ました。
composer update
数分後、テストが通らなくなりました。
さらに本番環境でもエラーが発生しました。
変更したファイルは0です。
Gitの差分もありません。
しかしアプリケーションは壊れています。
実際に起きていたこと
Composerは、composer.jsonを元に依存関係を解決します。
ここで重要なのがバージョン指定です。
"require": { "framework/core": "^4.2" }
この「^」は、4.xの最新まで許可する意味です。
つまり4.9が公開されれば、それも対象になります。
updateを実行すると次が起きます。
- 直接依存が更新
- 間接依存も更新
- 依存の組み合わせが変わる
ここで問題が発生します。
互換性は「保証」ではなく「期待」だからです。
間接依存が最も危険
今回壊した原因は、自分が入れていないライブラリでした。
フレームワークが内部で使っているパッケージです。
開発者が意識していない部分ほど影響が大きくなります。
例:
- ログライブラリの挙動変更
- 日付処理の仕様変更
- 例外クラスの変更
コードは触っていないのに挙動が変わります。
「昨日は通ったテスト」が突然落ちます。
なぜinstallでは起きないのか
ここで重要な違いがあります。
composer install
これはcomposer.lockを再現します。
つまり、以前と同じバージョンが入ります。
一方、
composer update
は、lockファイルを書き換えます。
依存関係の“新しい解”を求めます。
つまりupdateは修復ではなく再構築です。
よくある誤解:updateは安全なメンテナンスではない
多くの人が「とりあえずupdateしておくか」と考えます。
これはnpm感覚では自然です。
しかしComposerでは意味が違います。
- update:構成変更
- install:状態再現
この違いを知らないと、本番で事故が起きます。
実際の復旧手順
壊れたとき、最初にやるべきことは1つです。
git checkout composer.lock composer install
これで元に戻る可能性が高いです。
つまりcomposer.lockはバックアップでもあります。
その後、原因を調べます。
composer why-not パッケージ名 バージョン
どの依存が衝突しているかが分かります。
なぜPHPでこの問題が目立つのか
PHPはフレームワーク依存が強い傾向があります。
そしてフレームワークは多数のライブラリに依存しています。
結果として、
> 1つのupdateが数十パッケージに影響する
という状況になります。
これはComposer特有というより、エコシステムの特徴です。
注意点:本番環境でupdateを実行しない
最も危険な行為があります。
- 本番サーバーでcomposer update
これはデプロイではありません。
本番環境の再構築です。
環境差があると、開発と違う依存解決が行われる可能性もあります。
最悪の場合、再現不能バグになります。
まとめ:壊れたのはプロジェクトの前提だった
今回壊れた原因は、コードではありませんでした。
依存関係の前提条件です。
Composer updateは便利ですが、
それは「最新にしてくれる」からではありません。
> 依存関係を正しく表面化させるからです。
updateで壊れるプロジェクトは、実は以前から壊れる可能性を抱えていました。
たまたま固定されていただけです。
Composerは壊したのではなく、
隠れていた前提を露出させただけだった、というのが実感に近いです。