composerを使っているけど、どうやってバージョン指定をしたらいいんだろう? そんな初心者さん向けの記事です。

composer

言わずと知れた、PHPの依存ライブラリを管理してくれる便利なツールです。 詳しくはcomposer で依存ライブラリを管理をご覧ください。

composer.json

このファイルに依存ライブラリとバージョンを定義します。 例えばこのような感じですね。

"require": {
    "symfony/symfony": "~2.6",
    "knplabs/knp-menu-bundle": "1.1.0"
}

バージョン、何を指定したらいいの?

とあるライブラリでこのようなバージョンが公開されているとします。

3.0-dev
2.1
2.0
1.0

外部ライブラリの安定版を使用する

"vendor/foo": "~2.0"

2.x系の安定版を指定します。2.xのうち2.0以上で一番新しい2.1がインストールされます。

自社内ライブラリなど開発中の機能も取り込みたい

"vendor/foo": "3.*@dev"

3.x系を指定し、開発中バージョンも対象となるように@devフラグを付けます。 3.0-devがインストールされます。

まだバージョン番号がついていないライブラリ

"vendor/foo": "dev-master"

上記の例とは違い、まだバージョン番号がついていないライブラリを使いたいこともあると思います。 その場合はdev-master(masterブランチ)を指定します。

セマンティックバージョニング

まずバージョン番号がどのようについているのか理解しましょう。 packagistなどで公開されているライブラリの多くは、基本的にセマンティックバージョニングというバージョン管理方法に基づいて管理されています。(実際にはそうでないものもたくさんありますが…)

バージョンナンバーは、メジャー.マイナー.パッチとし、バージョンを上げるには、 1. APIの変更に互換性のない場合はメジャーバージョンを、 2. 後方互換性があり機能性を追加した場合はマイナーバージョンを、 3. 後方互換性を伴うバグ修正をした場合はパッチバージョンを上げます。 プレリリースやビルドナンバーなどのラベルに関しては、メジャー.マイナー.パッチの形式を拡張する形で利用することができます。

セマンティックバージョニングより引用

つまり「今まで2.0を使っていたけど3.0-devっていうのが出たから使っちゃおう、新しいほうがいいよね」とやみくもにバージョンアップするとライブラリを使用しているソースコードで動かない部分が出てきてしまう訳です。 ライブラリの管理者は後方互換性がない事と現在開発中である事を知らせています。利用者もバージョンについて理解して判断する必要がありますね。

よく分からない場合は最新安定版を指定し、changelogやreadmeを参考に使いたい機能やバグフィクスを探した上でバージョンアップを検討しましょう。

実際バージョンてどうやって指定するの?

使いたいバージョンが1つだけに限定されている場合は簡単ですね。

"vendor/foo": "1.0.0"

でも実際は「1.0.0が最新版だからこれを使いたいけど、バグフィクスが出たら自動的にとりこみたいな」という事のほうが多いですね。この時にセマンティックバージョニングを利用して、記号で対象となる範囲を指定することができます。

バージョン指定

指定 対象となるバージョン
1.* 1.x.x
1.2.* 1.2.x
~1.1 1.1以上、2未満
~1.1.5 1.1.5以上、1.2未満
>=1.2 1.2以上
~2.0,>=2.6 2.0以上3未満 かつ 2.6以上
>=2.0|3.0-beta 2.0以上 または 3.0beta版

例外的な使い方

指定 対象となるバージョン
1.0#123abc コミット指定
技術的な回避策のために使われるもので通常の使用は推奨されていません
~1 1.0以上、2未満(~1.0と同義)
メジャーバージョンを指定した場合は後方互換性のあるバージョンが対象となります

アスタリスク vs チルダ

1.* と ~1.0 は対象となるバージョンが同じです。 どっちを使ったらいいのでしょうか?

いろいろ調べてみてもベストプラクティスは見つかりませんでしたが、有名そうなライブラリのcomposer.jsonをいくつか見てみるとほとんどがチルダを使っていました。 1.*(文字列にマッチするバージョン)より~1.0(互換性を保ちつつ最新版を)と書いたほうがバージョン管理的に正しいのかな、と個人的に思っています。

サフィックス

ライブラリのブランチには管理者がサフィックスを設定できます。 通常はブランチの状態(スタビリティ)を示す特定のキーワードがつけられます。

安定度 サフィックス 状態(スタビリティ)
-dev 開発中
-patch バグ修正および機能追加中
-alpha α版(未実装の機能や不具合を含む)
-beta β版(機能が一通り動作する)
-rc 公開前(リリース候補における最終テスト中)
-stable(省略可) 安定版

https://getcomposer.org/doc/04-schema.md#version

スタビリティフラグ

どの状態(スタビリティ)を対象に含めるかをスタビリティフラグを使って指定することができます。 何も指定しない場合は自動的に安定版が対象となります。

公開されているバージョン
3.0-dev
2.0-alpha
1.8
1.7
スタビリティフラグを省略、安定版の1.8が対象となる
"vendor/foo": "<=3.0"

「まだベータ版だけど新機能をぜひ使いたい」ということもありますね。 このような場合にスタビリティフラグを使用します。

スタビリティフラグを使って対象のブランチをalphaまで広げる
"vendor/foo": "<=3.0@alpha"

最初の例を思い出してみましょう。 この例では@devを指定しているため全ての状態(スタビリティ)が対象になります。

自社内ライブラリなど開発中の機能も取り込みたい
"vendor/foo": "3.*@dev"

全てのライブラリで状態(スタビリティ)を指定する

たくさんの開発中バージョンのライブラリに依存しているような場合は、ひとつずつスタビリティフラグを指定するのは手間がかかります。このような場合には全ライブラリに対して許容する状態(スタビリティ)を指定します。

// composer.json
"minimum-stability":"dev", // 全ライブラリで対象をdevまで広げる
"prefer-stable": "true" // 最も安定したバージョンを選択

minimum-stabilityとスタビリティフラグを併用すると、スタビリティフラグが優先されます。

// composer.json
"minimum-stability": "dev",
"require": {
    ...
    "vendor/foo": "<=3.0@stable", // これだけ安定版
    ...
}

スタビリティはどこまで適用されるのか

スタビリティ指定(minimum-stability + スタビリティフラグ)

スタビリティフラグの適用範囲はルート(composer.jsonに書いたもの)のみです。

minimum-stabilityもルートにしか適用されないと記載していましたが、誤りでした。@kenji_sさん、ご指摘ありがとうございましたm(_ _)m

公式マニュアルに記載があるとおり、スタビリティフラグはroot-onlyな設定項目なので、依存先ライブラリのcomposer.jsonで指定されているスタビリティフラグは無視されます。

// composer.json
"require": {
    "vendor/foo": "1.0@alpha"
}
// vendor/foo/composer.json
"require": {
    "vendor/bar": "1.0@alpha" // この@alphaは適用されず、stableなバージョンがインストールされる
}

子の依存先のスタビリティを指定したい場合は、ルートのminimum-stability自体を下げるか、ルートのcomposer.jsonに直接の依存として明記する必要があります。

// composer.json
"require": {
    "vendor/foo": "1.0"
},
"minimum-stability": "alpha"

または

// composer.json
"require": {
    "vendor/foo": "1.0@alpha,
    "vendor/bar": "1.0@alpha" // スタビリティフラグをつけた依存で上書き
}

ただし、ルートのminimum-stabilityを下げる方法は基本的には推奨されません。 この方法では、安定版を取得可能なものも含めてすべての依存が不安定なバージョンで取得されてしまいます。(参考) 通常は、必要なものにスタビリティフラグをつける方法を選択してください。

公開されている状態(スタビリティ)とバージョンの指定方法について理解できたでしょうか。

スタビリティの話は少し複雑ですね。依存などの問題がなければ、最初はバージョン番号だけシンプルに書く方がいいと思います。

packagistにないライブラリを使いたい

リポジトリを追加することで、packagistで管理されていないライブラリ(例えばgithubでソースが公開されているだけのライブラリなど)を参照することができます。 だたしソースコード側でcomposer.jsonが用意されている必要があります。

"repositories": [
    { "type": "vcs", "url": "xxx.git" }
]

composerコマンド

install, updateだけでなく便利なコマンドが用意されています。いろいろ試して使ってみましょう。

https://getcomposer.org/doc/03-cli.md

composer show --self

composer.jsonで指定したバージョンの一覧を表示します。 grepと組み合わせればcomposer.jsonを開いて検索するより高速です。

composer show --installed

インストールされたバージョンの一覧を表示します。

composer depends --link-type=require [vendor/foo]

使わなくなったライブラリを削除するときに使います。 composer.jsonのライブラリのうちvendor/fooを必要としているものを表示します。

composer search [keyword]

packagistのサイトで検索するのと同じです。

composer show [vendor/foo]

searchで探した後、正式なライブラリ名で指定します。 有効なバージョン、依存ライブラリなどの情報を表示します。

終わり

composerを使い始めて1年弱、公式サイトの英語マニュアルを眺めたりネット検索したりしながら、ここまでのことをようやく最近理解できるようになりました。

composerのちょっとしたテクニックはいろいろなサイトに書いてありますが、初めてcomposer.jsonを開いた時にどうやってバージョンを指定したらいいか初心者向けに日本語で丁寧に説明しているサイトがないなあと思って、長々と書いてみました。

1年前の私と同じような初心者さんのお役に立てれば幸いです。