- 状況
- composer remove --update-with-dependencies でもだめだった
- 一番確実なのは composer.lock を作り直すことだが...
- ただ、バージョンが固定されておらず composer.lock を簡単に消せないことも
- ではどうすればいいのか
- composer.lock を読む
- どうやってそのライブラリをcomposer.lockから消すのか
- 具体的にやってみる
- まとめ
状況
composer.json
に直接記述されているライブラリAがある。- ライブラリAが依存しているライブラリBがある。
- ライブラリBが依存しているライブラリCがある。
このような状況の場合、 composer update
すると、composer.lock にライブラリA, ライブラリB, ライブラリCが記述される。以後、 composer install
するとこの3つのライブラリがinstallされる。
ライブラリAを使わなくなったので composer remove ライブラリA
した結果、 composer.json
からライブラリAは消えたが、 composer.lock
ではライブラリB, ライブラリCが消えない。結果、 composer install
すると、使われていないのにライブラリBとライブラリCがインストールされてしまう。どうはってこれらを composer.lock
から消したらいいか。
composer remove --update-with-dependencies でもだめだった
composer remove ライブラリA --update-with-dependencies
というコマンドがある。これを行うと、ライブラリAが依存していたライブラリにupdateがかかる。つまり、ライブラリBにupdateがかかり、もしライブラリBがどこでも使われていなかったら削除される筈なのだが...なぜか削除されない時がありました。
そもそも、 --update-with-depandencies
は composer 1.0.0-beta2 から deprecated になっており、普通に `composer remove今回のように依存性をうまく解決できないことが多かったのかもしれない。
一番確実なのは composer.lock を作り直すことだが...
一番確実なのは、 composer.lock
を消したうえで、 composer update
することだ。これにより composer.lock
内に記述されている依存関係が綺麗になるので、ライブラリBとライブラリCは綺麗に消える。
ただ、バージョンが固定されておらず composer.lock を簡単に消せないことも
ただし、そう簡単に composer.lock
を作り直すわけに行かない場合もあります。 composer.json
でしっかりバージョンが固定されていればよいのですが、必ずしもそうとは限らないからです。例えば以下のような記述があるとします。
"myclabs/php-enum": "dev-master", "guzzlehttp/guzzle": "~6.0"
こういった記述がされている場合、composer.lock
を生成し直すと、php-enum は、新しいcomposer.lock
を生成したときの最新のmasterのバージョンに変わってしまいますし、guzzleも5.x系のマイナーバージョンアップがされているとバージョンが変わってしまいます。
バージョンが変わってほしくないライブラリのバージョンが上がってしまうことにより、不具合が出現する可能性もあります。さらに、複数ライブラリのバージョンが上がってしまうとどれが原因で不具合が出たのかが不明になります。
ではどうすればいいのか
ではどうすればいいのか。結局は composer.lockを直接んで依存性を解決する しかありませんでした。
composer.lock を読む
composer.lock
ですが、これも結局jsonですので読めないことはないです。記述についても、 composer.json
に依存関係情報が追加されただけです。
- ライブラリAがライブラリBに依存している
- ライブラリBがライブラリCに依存している
という状況である今回、 composer.json
にはライブラリAの名前が書いてあるだけです。composer.lock
には以下の情報がかかれています。
- ライブラリAが依存しているライブラリの名前とバージョン
- ライブラリBが依存しているライブラリの名前とバージョン
- ライブラリCが依存しているライブラリの名前とバージョン
記述が増えただけで書いてある内容は同じなので、頑張れば「どのライブラリからも使われていないライブラリ」を求めることができるのです。
どうやってそのライブラリをcomposer.lockから消すのか
では、ライブラリAを消したとします。 composer.lock
を読むことで、ライブラリBが不要なことがわかりました。どうやって composer.lock
からライブラリBの記述を消したらいいでしょう。もちろん直接 composer.lock
を書き換えてもよいのですが、以下のコマンドで消すことができます。
composer update ライブラリB
このコマンドを叩くと、ライブラリBが使われていないことがわかった場合には、ライブラリBの情報を composer.lock
から消してくれます。
具体的にやってみる
今回僕が遭遇した状況は以下のような状況でした。
jenssegers/agent
というライブラリがあるのですが、これが今回不要になりました。*1- この
jenssegers/agent
ですが、illuminate/support
というライブラリに依存しています。 - さらに
illuminate/support
はparagonie/random_compat
というライブラリに依存しています。
このような場合は以下のようになります。
# jessegers/agent を削除 $ composer remove jenssegers/agent Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 0 installs, 0 updates, 2 removals - Removing jenssegers/agent (v2.3.3) - Removing mobiledetect/mobiledetectlib (2.8.22) Writing lock file Generating autoload files # 依存しているが何故か消えないライブラリを消す $ composer update illuminate/support Package "illuminate/support" listed for update is not installed. Ignoring. Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 0 installs, 0 updates, 1 removal - Removing illuminate/support (dev-master c2f8d83) Writing lock file Generating autoload files $ composer update paragonie/random_compat Package "paragonie/random_compat" listed for update is not installed. Ignoring. Loading composer repositories with package information Updating dependencies (including require-dev) Package operations: 0 installs, 0 updates, 1 removal - Removing paragonie/random_compat (v1.x-dev 1115ffa) Writing lock file Generating autoload files
まとめ
composer remove XXXX
で不要なパッケージを消すことができるが、稀にcomposer.lock
から依存がうまく消えないことがある。composer.lock
を再生成すれば依存関係は綺麗になるが、composer.json
でバージョンをちゃんと固定していないと辛い- 結局
composer.lock
を読んで頑張って解決した...