パッケージと制約
ComposerのバージョンとVCSのバージョン
Composerはgitのような版管理システムを活用する方向に大きく舵を切っているため、「バージョン」という用語は少し曖昧です。
版管理システムの意味では、「バージョン」は特定のデータを含む特定のファイルの集まりです。
gitの用語法では、これは「ref」もしくは特定のコミットのことです。
これはブランチのHEADやタグで表されることがあります。
あるバージョン……例えばタグv1.1
やコミットe35fa0d
……がVCSにあることを確認するには、単一の既知のファイルの集まりが欲しいものであり、常に同じファイルが取り寄せられます。
Composerで何気なくバージョンとしてよく指すもの……つまり要件の行でパッケージ名に続く文字列(例えば~1.1
や1.2.*
)……とは実のところ、より具体的にはバージョン制約です。
Composerはバージョン制約を使い、VCSからチェックアウトすべきrefを調べます(もしくは、composer.json
中のversion
指定で静的に維持されたライブラリのときは、与えられたライブラリが許容されるか検証します)。
VCSのタグとブランチ
以下の説明では、以下のライブラリリポジトリ例があるとします。
~/my-library$ git branch
v1
v2
my-feature
another-feature
~/my-library$ git tag
v1.0
v1.0.1
v1.0.2
v1.1-BETA
v1.1-RC1
v1.1-RC2
v1.1
v1.1.1
v2.0-BETA
v2.0-RC1
v2.0
v2.0.1
v2.0.2
タグ
通常Composerはタグを扱います(ブランチではありません。
意味するところが分からなければ、版管理システムをご一読ください)。
バージョン制約を書くとき、特定のタグ(例えば1.1
)を参照することや、有効なタグの範囲(例えば>=1.1 <2.0
や~4.0
)を参照することがあります。
こうした制約を解決するため、ComposerはまずVCSに全ての利用できるタグを挙げるよう頼みます。
それからこれらのタグに基づいて利用できるバージョンの内部的な一覧を作ります。
上の例では、composerの内部リストにはバージョン1.0
、1.0.1
、1.0.2
、1.1
のベータリリース、1.1
の1つ目と2つ目のリリース候補、1.1
の最終リリースバージョンなどが含まれます(なおComposerは最終的に有効なバージョン番号を得るため、自動的に実際のタグ名からv
接頭辞を除きます)。
ComposerにVCSで利用できるバージョンの完全な一覧ができたら、プロジェクトの全てのバージョン制約に合致する最も大きいバージョンを探します(他のパッケージが自分で指定したものよりそのライブラリのバージョンをより限定されたものを要件とすることがあります。
そのため選ばれるバージョンは入手できるバージョンのうち最大のものであるとは限りません)。
またそのタグのzipアーカイブをダウンロードしてvendor
ディレクトリの正しい場所に開封します。
ブランチ
タグではなくブランチをチェックアウトしたいときは、特別なdev-*
接頭辞(接尾辞のときもあります。後述)を使ってブランチを指す必要があります。
ブランチをチェックアウトすると、ブランチで作業したいと仮定し、実際にリポジトリをvendor
ディレクトリの正しい場所にクローンします。
タグについては、実際にはリポジトリをクローンせず、正しいファイルを複製します(--prefer-sourceや--prefer-distでこの挙動を変えられます。
インストールオプションを参照してください)。
上の例ではmy-feature
ブランチをチェックアウトしたいため、require
節のバージョン制約としてdev-my-feature
を指定することになります。
こうするとmy-liberay
リポジトリがvendor
ディレクトリにクローンされ、my-feature
ブランチがチェックアウトされます。
ブランチ名がバージョンのように見えるとき、タグではなくブランチをチェックアウトしようとしていることをはっきりしなければなりません。
上の例では2つのバージョンブランチv1
とv2
があります。
これらのブランチをチェックアウトするにはv1.x-dev
のようにバージョン制約を指定しなければなりません。
.x
は任意の文字列で、v1
タグではなくv1
ブランチについて書いていることをComposerに伝えます(代替としてブランチにv1
ではなくv1.x
と名前を付けられます)。
この場合のバージョンのような名前(この場合はv1
)を持つブランチでは、dev-
を接頭辞として使うのではなく、接尾辞として-dev
を付けます。
安定性
Composerは次の安定性を(この順で)認識します。
すなわちdev、alpha、beta、RC、stableです。
ここでRCはリリース候補 (release candidate) を表します。
バージョンの安定性は接尾辞で定義されます。
例えばバージョンv1.1-BETA
にはbeta
の安定性があり、v1.1-RC1
にはRC
の安定性があります。
そのような接尾辞がないときは、バージョンがstable
だと見做します。
例えばv1.1
です。
これに加えて全ての番号のブランチに-dev
接尾辞を自動的に加え、VCSリポジトリからインポートしたその他全てのブランチにdev-
の接頭辞を加えます。
両方の場合とも安定性dev
が割り当たります。
このことを念頭に置くと、次の節を読む助けになります。
最小安定性
チェックアウトされてプロジェクトに加わるライブラリのVCSの、ファイルに作用する点はもう1つあります。
Composerでは安定性の制約を指定し、正当と見做すタグを制限できます。
上の例で、最終的な公式リリースの前に、バージョン1.1
にベータ版と2つのリリース候補が、ライブラリでリリースされていることにご注目ください。
composer install
やcomposer update
を走らせるときにこれらのバージョンを取得するには、リリース候補やベータリリース(または所望であればアルファリリース)で良いことをComposerに陽に伝えなければなりません。
これにはプロジェクト範囲のminimum-stability
値をcomposer.json
に使うか、バージョン制約に「安定性フラグ」を使います。
詳しくはスキーマのページをお読みください。
パッケージ制約を書く
Composerでのバージョンの捉え方が分かったところで、プロジェクトの依存関係でバージョン制約を指定する方法についてお話ししましょう。
厳密なパッケージ制約
パッケージの厳密なバージョンを指定できます。 こうすると、このバージョンを、それもこのバージョンだけを、Composerにインストールするよう伝えます。 他の依存関係で違うバージョンが必要なとき、解決器は最終的に失敗し、インストールや更新の処理を途絶します。
例:1.0.2
バージョンの範囲
比較演算子を使うと、正当なバージョンの範囲を指定できます。
正当な演算子は>
、>=
、<
、<=
、!=
です。
複数の範囲を定義できます。
空白 (
) やコンマで区切られた範囲は論理積として扱われます。
二重パイプ (||
) は論理和として扱われます。
積は和より優先されます。
補足: 境界のない範囲を使うときはご注意ください。 後方互換性を壊すバージョンを予期せずインストールすることがあるからです。 安全のため、代わりにキャレット演算子を使うことをご検討ください。
補足: Composerの古いバージョンでは、単一の棒 (
|
) は論理和の推奨される代替案でした。 そのため後方互換性のため、単一の棒 (|
) は論理和として扱われたままになっています。
例:
>=1.0
>=1.0 <2.0
>=1.0 <1.1 || >=1.2
ハイフン版のバージョン範囲 (-
)
含まれるバージョンの集合です。
含まれるバージョンの右部分はワイルドカードが補完されます。
例えば1.0 - 2.0
は、2.0
が2.0.*
になるため、>=1.0.0 <2.1
と等価です。
他方で1.0.0 - 2.1.0
は>=1.0.0 <=2.1.0
と等価です。
例:1.0 - 2.0
ワイルドカードのバージョン範囲 (.*
)
*
ワイルドカードでパターンを指定できます。
1.0.*
は>=1.0 <1.1
と等価です。
例:1.0.*
次の大規模リリースの演算子
チルダのバージョン範囲 (~
)
~
演算子は例で説明するのが1番です。
~1.2
は>=1.2 <2.0.0
と等価です。
一方、~1.2.3
は>=1.2.3 <1.3.0
と等価です。
見て分かる通り、セマンティックバージョニングを尊重するプロジェクトで特に有用です。
よくある使い方は、~1.2
のように(こうすると2.0までの全バージョン、ただし2.0は含まれないものにできます)、依存する最小の小規模バージョンの印を付けることでしょう。
理論上は2.0まで後方互換性の破壊はないでしょうから、うまくいきます。
別の見方は、~
を使って最小バージョンを指定するというものです。
ただし指定された最後の桁は上げられます。
例:~1.2
補足::
2.0-beta.1
は2.0
より厳密には前ですが、~1.2
のようなバージョン制約ではインストールされません。 前述の通り、~1.2
とは.2
が変わることがありますが、1.
の部分は固定されるという意味です。
補足:
~
演算子にはメジャーリリース番号に関して挙動に例外があります。 つまり、例えば~1
は~1.0
と同じですが、これは後方互換性を保とうとする上で、メジャー番号を増やせないからです。
キャレットバージョン範囲 (^
)
^
演算子はとてもよく似た挙動ですが、よりセマンティックバージョニングに密接しており、破壊的でない更新は常に許されます。
例えば^1.2.3
は>=1.2.3 <2.0.0
と等価です。
2.0までのリリースで後方互換性を壊すものはないからです。
1.0より前のバージョンについては、安全性に留意した動作となっており、^0.3
は>=0.3.0 <0.4.0
として、^0.0.3
は>=0.0.3 <0.0.4
として扱います。
これはライブラリのコードを書く際に、最も相互運用性を高くするため推奨される演算子です。
例:^1.2.3
補足: WindowsでPowerShellを使っているとき、例えば
composer require
コマンドを使う際は、CLIで引数としてキャレットを使うときにエスケープしなければなりません。 キャレットがComposerに確実に正しく渡されるようにするため、例えば^^^^1.2.3
のように、4つの連続するキャレット演算子を使わなければなりません。
安定性の制約
安定性を陽に定義しない制約を使うとき、使われた演算子により、Composerは内部的に既定を-dev
または-stable
にします。
これは透過的に起こります。
比較で安定リリースのみを陽に検討したいときは-stable
接尾辞を加えてください。
例:
制約 | 内部 |
---|---|
1.2.3 | =1.2.3.0-stable |
>1.2 | >1.2.0.0-stable |
>=1.2 | >=1.2.0.0-dev |
>=1.2-stable | >=1.2.0.0-stable |
<1.3 | <1.3.0.0-dev |
<=1.3 | <=1.3.0.0-stable |
1 - 2 | >=1.0.0.0-dev <3.0.0.0-dev |
~1.3 | >=1.3.0.0-dev <2.0.0.0-dev |
1.4.* | >=1.4.0.0-dev <1.5.0.0-dev |
しかし制約の水準に強制せず様々な安定性を許すには、@<安定性>
(例:@dev
)のように安定性フラグを使い、与えられたパッケージが既定の最小安定性の設定とは違う安定性でインストールできることをComposerに知らせます。
使える全ての安定性フラグはスキーマのページの最小安定性の節に挙がっています。
まとめ
"require": {
"vendor/package": "1.3.2", // 1.3.2ぴったり
// >, <, >=, <= | 上限と下限を指定
"vendor/package": ">=1.3.2", // 1.3.2以上の全バージョン
"vendor/package": "<1.3.2", // 1.3.2より小さい全バージョン
// * | ワイルドカード
"vendor/package": "1.3.*", // >=1.3.0 <1.4.0
// ~ | 最後の桁は上げられます
"vendor/package": "~1.3.2", // >=1.3.2 <1.4.0
"vendor/package": "~1.3", // >=1.3.0 <2.0.0
// ^ | 破壊的な変更を許しません(セマンティックバージョニングに従い、メジャーバージョンは固定です)
"vendor/package": "^1.3.2", // >=1.3.2 <2.0.0
"vendor/package": "^0.3.2", // >=0.3.2 <0.4.0 // メジャーバージョンが0のときは例外
}
パッケージ制約の確認
semver.madewithlove.comを使ってバージョン制約を確認できます。
パッケージ名を埋めると、Composerによりcomposer.json
ファイルに加わる既定のバージョン制約が自動で埋まります。
バージョン制約を調整すると、ツールにより、合致する全てのリリースが強調されます。