composerでサードパーティライブラリを読み込む

composerでサードパーティライブラリを読み込み方法を解説します。carbonという時間操作ライブラリを教材に、サンプルコードを眺めながら進めていきます。なお、サンプルコードの実行にはPHP(7系統)、composerがインストールされている必要があります。

サンプルコード
https://github.com/kaidouji85/php-thrd-party-lib

# サンプルコードを動かす

```php5:main.php
<?php
require("vendor/autoload.php");

use Carbon\Carbon;

$tommorow = Carbon::now()->addDay();
print($tommorow);
```

上記コードは、[carbon](https://carbon.nesbot.com/docs/)という時間操作ライブラリを使用して実行日 + 1日を表示するプログラムです。なにはともあれ、まずはプログラムを動かしてみましょう。お手元の環境でコマンドラインを開いてください。

```sh
cd <作業フォルダ>
git clone git@github.com:kaidouji85/php-thrd-party-lib.git
php main.php
```

上記リポジトリにはcarbonが含まれていないので、エラーで落ちます。そんな欠陥リポジトリをアップしたのかよと思いますが、```composer install```を実行してみてください。

```sh
composer install
# vendor配下に色々とファイルがダウンロードされる

php main.php
```

今度は成功したと思います。```composer install```でcarbonをダウンロードできたのですが、ここで一つ疑問が生じます。同コマンドにはcarbonが一文字も含まれていませんが、なぜかvendorには正しいファイルが置かれています。carbonをダウンロードせよ、という命令はどこに書かれているのでしょうか。その答えはcomposer.jsonです。

# composer.json

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

composer.jsonを見ると、carbonとハッキリ書かれています。```composer install```はここを見て、必要なライブラリをダウンロードしていました。めでたし、めでたし......、ではありません。先ほどvendorフォルダにサードパーティライブラリがダウンロードされると言いましたが、念のために確認しておきましょう。

![vendor配下.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26979/0c8d27ca-b4b0-e1a4-d23c-c15cc8df9e97.png)
**※vendor配下の中身は環境、実行日時によって微妙に違うことがあります。**

vendor配下にはcarbon以外のファイルが含まれています。これらはcomposerで内部的に必要となるおまじないなのかというと、それ以外も含まれます。例えばcarbonが内部的に使っているライブラリなどです。

# 依存ライブラリ
carbonが自分コードだけで完結しているかというと、そうではありません。carbonもサードパーティライブラリを使っています。下図のように、自分では1個だけライブラリを使っているつもりでも、依存関係を紐解くと沢山のライブラリが内部的に使われていることが分かります。

![依存ライブラリの階層構造.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26979/921c7f8e-1241-f618-a1b4-7966d55cd724.png)

carbonの依存ライブラリを、少しだけ確認しましょう。

carbon
https://packagist.org/packages/nesbot/carbon

「requires」がcarbonが依存しているライブラです。その中に「symfony/translation」となるので、これも見てみましょう。

symfony/translation
https://packagist.org/packages/symfony/translation

symfony/translationも「requires」には色々と書かれています。これをひたすら繰り返して、必要なライブラリを全てリストアップすると膨大な量になることは想像に難くないと思います。

# バージョン指定問題

めでたし、めでたし、といきたいところですが、そうは問屋が卸しません。実はcomposer.jsonだと、```composer install```をした時期によって、ダウンロードされるライブラリのバージョンが微妙に違ってきます。もう一度、composer.jsonを見てみましょう。

```json:composer.json
        "nesbot/carbon": "^2.30"
```

composerはセマンティックバージョンに準拠していますが、数字の前についている^が気になります。結論から言うと、```^2.30```という書き方だと2.30 <= (バージョン) < 3.0.0までがダウンロードされる可能性があります。例えば、上の書き方だと、2.5.1がダウンロードされることがあります。バージョン指定の詳細は、composer公式ドキュメントにまとめられています。

composer バージョン指定
https://getcomposer.org/doc/articles/versions.md#summary

公式ドキュメントによると、```2.30```と書けばそれ以外のバージョンがインストールされることはありません。これで問題が解決するのかというと、依存ライブラリがバージョン固定をしていないと同じ問題が起こります。少なくともcarbonの「requires」を確認するとバージョン固定をしていないので、carbonが依存しているライブラリはインストール時期によって微妙に異なる場合があります。

上記の書き方が悪いとは一概に言えず、例えばバグフィックス版を自動的にインストールしてくれるというメリットがあります。ただ、そのメリットよりも、バージョン違いによるデグレの方が痛いですよね。この問題を解決するために、composerにはcomposer.lockという仕組みがあります。

# composer.lock
composer.lockとはvendor配下に含まれる全てのライブラリを書き出したものです。もちろんバージョン情報もついているので、全部のライブラリのバージョンをそろえることが出来ます。先ほど```composer install```はcomposer.jsonを見ると言いましたが、より正確には初めにcomposer.lockを確認して、存在しない場合にcomposer.jsonを見る、という挙動をします。また、composer.jsonからダウンロードした場合にはcomposer.lockが作られます。

![composer install 参照先 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26979/6864db2a-43a2-8e8e-3dfe-28f621c6cf99.png)

# オートロード
ここまでお膳立てができたら、後はライブラリを呼び出すだけです。vendor配下のnesbot/carbonをrequire_onceすれば大丈夫そうな気がしますが、それでは動きません。これまでさんざん説明したように、carbonを使うためには沢山のライブラリが必要になります。論理的にはcarbonが内部的に使っているライブラリをrequired_onceしなければ、動かない可能性があります。また、ライブラリによっては読み込む順番が大いに影響する可能性もあります。これを手動でやるのは面倒なので、composerにはオートロードという便利な仕組みがあります。

vendorフォルダ直下にautoload.phpというフォルダがあります。これは```require_once("vendor/autload.php)```とすることで、vendor配下にある全てのライブラリを自分のプロジェクトに読み込んでくれるというものです。オートロード経由なら読み込む順番、読込漏れを気にする必要はありません。

なお、```require_once("vendor/autoload.php")```はエントリポイントで1回書けば大丈夫です。サンプルプログラムではmain.phpでrequire_onceしてますが、それ以外のファイルを作った場合はオートローダーをrequire_onceする必要はありません。

# gitとcomposer
最後にcomposer関連ファイルでgitに含めるべきもの、そうでないものをまとめます。結論は以下の通りです。

**gitに含めるべき**
* composer.json
* composer.lock

**gitignore(gitに含めないべき)**
* vendorフォルダ

composer.lockがあればライブラリを完璧に再現することができるので。composer.jsonはいらないと思いますす。しかし、自分が本当に使っているライブラリが書かれているのはcomposer.jsonだけです。composer.lockだけで、自分が使っているのはcarbonだけだと判断できるでしょうか。carbonを使っているという情報がない場合、ライブラリのバージョンアップをする時にとても困ります。composer.json、composer.lockはペアでgit管理しましょう。

vendorフォルダですが、全ライブラリがダウンロードされるためにファイルサイズが大きくなりがちです。また、vendorフォルダはサードパーティライブラリ置き場なので基本的に編集することはなく、```composer install```でいつでも再作成が可能です。なので、原則としてgit管理はしません。

# まとめ
長かったですが、今までの話をまとめます。

* composer.jsonに自分が使うライブライを定義する
* composer.lockには依存ライブラリが全て書かれている
* vendorにはダウンロードしたライブラリが配置される
* ライブラリ読込はエントリポイントで```require_once("vendor/autoload.php")```とやろう
* composer.json、composer.lockはgit管理しよう
* vendorは.gitignoreに追加しよう

以上です。composerを使いこなして、楽しいPHPライフを過ごしましょう。