(タイトルがややこしくてすみません)
Packagistに公開されているライブラリ(以下somepackage)をインストールしようとしたところ、既存のライブラリ(以下requiredpackage)に依存しており、そのバージョンが古いためにsomepackageの最新バージョンを入れることができないということがありました。
requiredpackageは既に複数のファイルで使用しており、バージョンアップがすぐにはできない状況でした。
そこでsomepackageをサブモジュール化して、別のcomposer.json
で管理するという戦略を取ったのでその内容を紹介します。
環境
# composer -V
Composer version 1.10.22 2021-04-27 13:10:45
# php -v
PHP 7.4.7 (cli) (built: Jun 11 2020 18:41:17) ( NTS )
# php artisan --version
Laravel Framework 6.18.35
状況の整理
somepackageには下記の要件がありました。
"require": {
"requiredpackage": "^1.8.4||^2.2.1"
}
リポジトリは要件を満たしていません。
src# composer show | grep requiredpackage
requiredpackage 1.6.1
やったこと
サブモジュールとしてsrc/lib/somepackage
ディレクトリを切り、composer.json
を置きます
{
"require": {
"somepackage": "2.12.x"
},
}
src/lib/somepackage
でcomposer install --dump-autoload
するとそれぞれ異なるバージョンがインストールされた状態になります
src/lib/somepackage# composer show | grep requiredpackage
requiredpackage 2.4.0
src# composer show | grep requiredpackage
requiredpackage 1.6.1
この時点でsomepackageはサブモジュールのautoloadを利用してインポートができる状態になりました。
しかし、src/lib/somepackage/vendor
の一部パッケージがsrc/vendor
と重複していると、ファイルのインポート時に名前空間で競合が発生する可能性があります(つまり意図通りのバージョンのパッケージを参照できない可能性がある)。
今回はsomepackageをインポートするファイルが限られていたので、使用するファイルで直接requireする方針を採用しました。
require base_path('lib/somepackage/vendor/autoload.php');
somepackageの依存パッケージがsrc/vendor
にも存在している場合は依然として名前空間の競合が発生する可能性はありますが、影響範囲は限定されます。
本来であればバージョンアップすべきですが、一時的な対応としてはアリかなと思います。