ComposerによるPHPパッケージ管理の基礎知識

# Composerとは

Composerは、PHPのパッケージ管理ツールです[^1]。

パッケージというのは、特定の用途のために作成されたプログラム群のことで、具体的にはPHPUnit(テスト・ツール)やCarbon(日付操作で使われる)などを指します。

[^1]: パッケージとは、特定の用途のために作成されたプログラム群のこと

## Composerを使うメリット

なぜComposerを使ってインストールするのか、というと、それは次のようなメリットがあるからです。

* パッケージをインストールする際、それが動作するために必要な他のパッケージも自動でインストールしてくれる[^2]
* インストールしたパッケージをファイル(composer.json)に記録するので、メンバと同じ開発環境を簡単に再現できる
* プログラム内でクラスを呼び出したとき、自動的にそのファイルを読み込んでくれるようになる(オートロード機能)
* インストールしたパッケージは決まったディレクトリ内に保存されるため、自分の作業結果と区別しやすい

[^2]: 必要な他のパッケージもインストールすることを、パッケージの依存関係の解決という

# Composerの使い方

Composerの基本的な使い方を紹介します。

## Composerのインストール

Macであれば、下記コマンドで簡単にインストールできます。

```
% brew install composer
```

インストールされたことを確認するために、下記コマンドを実行しました。

```
% composer -V
Composer version 1.9.0 2019-08-02 20:55:32
```

公式サイトで、各環境に合わせたインストール方法が紹介されているようです。

Composer公式サイト
https://getcomposer.org/


## requireコマンドによるパッケージインストール

実際にパッケージをインストールするため、新規ディレクトリ内で下記コマンドを実行しました。

```
% composer require nesbot/carbon
```

これはCarbonという日付操作のためのパッケージをインストールするコマンドです。

このように`composer require [パッケージ名]`で任意のパッケージをインストールすることができます。インストールすることができるパッケージは、[Packagist](https://packagist.org/)というサイトで検索することができます[^3]。

[^3]: Packagistは、Composerがデフォルトでパッケージを検索するサイトで、このようなサイトをリポジトリと呼ぶ

インストールが完了すると、次のようなファイルとディレクトリが作成されています。

```
% tree -L 1
.
├── composer.json
├── composer.lock
└── vendor

1 directory, 3 files
```

インストールされたパッケージは、vendorディレクトリ内に保存されています。

ちなみに、現在インストールされているパッケージを確認するときは、`composer show`コマンドを実行します。

```
% composer show
nesbot/carbon                 2.30.0  An API extension for DateTime that supports 281 different languages.
symfony/polyfill-mbstring     v1.14.0 Symfony polyfill for the Mbstring extension
symfony/translation           v5.0.4  Symfony Translation Component
symfony/translation-contracts v2.0.1  Generic abstractions related to translation
```

Carbonパッケージと一緒に、それが依存している他のパッケージもインストールされていることがわかります。

## インストールしたライブラリを使う方法

インストールしたCarbonライブラリが実際に使用できるのか試しました。

さきほどCarbonをインストールしたディレクトリ内に、次のようなファイルを作成しました。

```index.php
<?php

require_once 'vendor/autoload.php';

use Carbon\Carbon;

echo new Carbon();
```

このファイルを実行すると、次のように表示されます。

```
% php index.php
2020-02-29 00:27:45%
```

この`index.php`は、最初に`vendor/autoload.php`というファイルを読み込んでいますが、これによりComposerのオートロード機能が使えるようになります。

オートロードというのは、プログラム内でクラスを読み出したときに、自動的にそのファイルを読み込んでくれる機能です。つまり、`use Carbon\Carbon;`と記述するだけで、Carbon\Carbonという名前空間が割り当てられたクラスファイルを自動的に読み込んでくれる機能です。

## composer.jsonとは

`composer.json`は、インストール対象のパッケージを定義するファイルです。

ここにインストールしたいパッケージを記述して、`composer install`コマンドを実行すると、記述しておいたパッケージがまとめてインストールされます。

さきほどCarbonパッケージをインストールするために、下記コマンドを実行しました。

```
% composer require nesbot/carbon
```

すると、次のようなcomposer.jsonファイルが自動で作られます。

```composer.json
{
    "require": {
        "nesbot/carbon": "^2.30"
    }
}
```

"require"という変数名で定義されているパッケージが、インストール対象のパッケージです。"^2.30"と記述されている部分は、パッケージのバージョンです。

## composer.jsonを基にパッケージをインストール

`composer install`というコマンドを実行すると、`composer.json`でインストール対象に定義したパッケージをまとめてインストールすることができます。

新しくディレクトリを作成して、そのなかに`composer.json`という名前のファイルを作成して、次のように記述してみます。

```composer.json
{
    "require": {
        "nesbot/carbon": "^2.30"
    }
}
```

これを保存し、`composer install`コマンドを実行します。

```
% composer install
```

このように`composer.json`の情報を元にパッケージをインストールするこができるため、開発メンバとパッケージ環境を統一したいときなども、`composer.json`を共有して`composer install`を実行するだけでよいわけです。

## composer.lockとは

`composer.lock`は、インストールするパッケージのバージョンを定義するファイルです。

パッケージをインストールするときに`composer.lock`が存在する場合は、`composer.lock`に定義されたバージョンのパッケージがインストールされます。

また、パッケージをインストールするときに`composer.lock`が存在しない場合は、`composer.json`の定義を元にパッケージをインストールし、そのときインストールしたパッケージのバージョンを`composer.lock`ファイルを作成して記録します。

このおかげで、開発メンバ全員が同じバージョンのパッケージを使うことができます。

## updateコマンドによるパッケージの更新

`composer update`は、`composer.lock`を無視して、`composer.json`の情報を元にパッケージをインストールするためのコマンドです。`composer.json`で定義したパッケージの最新バージョンがインストールされ、`composer.lock`もそのバージョンに更新されます。

「`composer.json`で定義したパッケージの最新バージョン」という表現は、少しわかりづらいかもしれません。`composer.json`では、次のようにパッケージのバージョンを指定することができます。

```
"vendor/foo": "~1.1"
```

これは「1.1以上かつ2未満」という意味になるようです。

下記のサイトで詳しく説明してくださっています。

https://tech.quartetcom.co.jp/2015/01/19/composer-practices/

つまり、この場合は`composer update`によって、vendor/fooパッケージのバージョン1.1以上かつ2未満で最新のものがインストールされる、ということです。

ちなみにバージョンは、ドットで区切った3つの数字で表現されますが、

> 
| 位置 | 名前| 説明 |
|:-:|:-:|:-:|
| 左端の数字  | メジャーバージョン  | 後方互換性が維持されない機能を追加した場合に、数字が増えます。  |
|  真ん中の数字 | マイナーバージョン  | 後方互換性を維持した機能を追加した場合に、数字が増えます。  |
| 右側の数字  | パッチバージョン  | バグフィックスなどを追加した場合（後方互換性を維持している）に、数字を増やす。  |
 ※「後方互換性」というのは、「以前のバージョンで動いていた部分は、新しいバージョンでもそのまま動く。」ということを意味しています。

と下記のサイトで説明してくださっていました。

https://laboradian.com/php-composer/#1_Composer

## "composer install"と"composer update"の違い

"composer install"と"composer update"の違いをまとめます。

### composer install

* `composer/lock`があれば、それを元にパッケージをインストールする
* `composer.lock`がない場合は、`composer,json`を元にパッケージをインストールし、そのパッケージの情報を`composer.lock`を作成して記録する

### composer update

* `composer.json`に記述されたパッケージの最新バージョンをインストールし、そのパッケージ情報に`composer.lock`を更新する

## Gitを使用する場合

上述の通り、`composer.json`と`composer.lock`を共有して`composer install`を実行すれば、開発メンバで同じパッケージ環境を構築することができます。

そのため、Gitでバージョン管理する場合は、`composer.json`と`composer.lock`は管理対象に含める必要があります。インストールされたパッケージは、vendorディレクトリに保存されますが、.gitignoreに/vendorを追記して、vendorディレクトリは管理対象から外しておくのが一般的らしいです。

## 開発環境でのみ使用するパッケージを定義

本番環境と開発環境で、インストールするパッケージをわけることもできます。

`composer.json`に"require-dev"に含めたパッケージは、開発環境でのみインストールする、という意味になります。

たとえば、次のように--devオプションをつけてrequireコマンドを実行してみます。

```
% composer require nesbot/carbon
% composer require --dev phpunit/phpunit
```

上記を実行すると、`composer.json`は次のように作成されます。

```composer.json
{
    "require": {
        "nesbot/carbon": "^2.30"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.0"
    }
}
```

"require-dev"に記述されたパッケージは、開発環境でのみインストールされます。

実際に試してみるために、インストール済みのパッケージをいったん削除します。

```
% rm -r vendor
```

"require-dev"のパッケージはインストールしたくない、という場合は、下記のように--no-devオプションを使用してインストールを実行します。

```
% composer install --no-dev
```

オプションなしで`composer install`を実行すれば、"require"と"require-dev"両方のパッケージがインストールされます。

## よく使いそうなコマンド

### composer init

対話形式で`composer.json`ファイルを作成します。

### composer create-project

次のようにコマンドでフレームワークを使ったプロジェクトを作成できるようです。

```
% composer create-project --prefer-dist laravel/laravel blog
```

### composer require

`composer require [パッケージ名]`で好きなパッケージをインストールできます。

インストールしたパッケージの情報は`composer.json`と`composer.lock`に反映されます。--devオプションをつけると、開発環境でのみインストールするパッケージとして、`composer.json`の"require-dev"に追加されます。

### composer install

`composer/lock`があれば、それを元にパッケージをインストールします。

`composer.lock`がない場合は、`composer,json`を元にパッケージをインストールし、そのパッケージの情報を`composer.lock`を作成して記録します。

### composer update

`composer.json`に記述されたパッケージの最新バージョンをインストールし、そのパッケージ情報に`composer.lock`を更新します。

### composer remove

`composer remove [パッケージ名]`を実行すると、インストールされたパッケージを削除して、`composer.json`も更新してくれます。

ただし、ここで削除するパッケージが依存している他のパッケージは削除されないため、注意したほうがよさそうです。--update-with-dependenciesというオプションをつけることで、削除するパッケージだけに依存されているパッケージも一緒に削除できるらしいです。

```
% composer remove --update-with-dependencies nesbot/carbon
```

### composer dump-autoload

オートロードのためのクラスマップを作成するコマンドのようです。