phpのcomposerで自作ライブラリを管理

## 環境

- Gentoo Linux
- php7.2.10
- composer 1.7.2
- composer初心者

## 背景

composerを使えば、サードパーティのパッケージの管理は簡単である、という記述を散見するし、最近おさわりしてるlaravelさんもphpのパッケージについてはcomposerで管理しているらしいことがわかる。
そこで、自分で作ったパッケージもcomposerで管理したいなあと考えた。
laravelさんのcomposer.jsonにrequireして、他の子たちと一緒にvendor下にいてもらえれば、autoload.phpの恩恵にも預かれるし、良いのではないかと。
[公式ドキュメント](https://getcomposer.org/doc/) に全部書いてあるけども、一応自作パッケージをcomposerで入れることができたのでそこまでをメモ。
あまり深掘りはできていないので、さわりの部分だけのメモ。
laravelもそうだけどあんまりチュートリアル見たいのがないのよねえ、phpのドキュメントって。。

## まとめると

- 自分でパッケージを作って
- composerに管理させて
- 別のプロジェクトで使う
- gitのプライベートリポジトリでパッケージは管理したい（公開したくない）

こんなことがやりたい。

## composerのパッケージ

パッケージはディレクトリである、ような記述を公式サイトで見た通りで、パッケージのディレクトリをプロジェクトと読み替えればわかりやすいか。
基本的には [Packagist](https://packagist.org/) というところで管理されている。

## 公開したくないパッケージ

自分のパッケージに関しては公開できないもののため（仕事上のものとか）Packagistを使えない。
だけれどもやっぱりcomposerの恩恵には預かりたい。
これについては、composer.jsonを適切に書いてやればプライベートリポジトリなども参照可能であった。

## タグでバージョン管理

パッケージをダウンロードする際に、composer.jsonでは特定のバージョンを指定することができる。
gitなどであればタグやブランチに v で始まるバージョン(v1.0.0)などをつけておけばそれを見てくれるらしい。

## パッケージの管理

自作パッケージは適当なvcsに入れておけばそれを参照できるらしい。
自分の環境の場合は、ローカル環境にgitのリモートリポジトリを作って ssh でアクセスしている（ssh://&lt;user&gt;@&lt;host&gt;/path/to/&lt;package&gt;.git）
パスワードがついていても `composer install` 時に入力を促された。
vcsを使わない管理もできるのかな？オフィシャルにはzipのアーカイブを持ってくる例もあったけど、あれも結局urlだったし。

## ディレクトリ構成

### パッケージ

基本的には以下のようになるらしい。
必ずしもこうでなければいけない、ということもないようだけどまあ、一般的にはこんなかんじなので理由がなければ従うが吉。

<pre>
&lt;package&gt;/
    .git/
    .gitignore
    composer.json
    src/
        &lt;namspace&gt;/
            &lt;class&gt;.php
    tests/
        &lt;namspace&gt;/
            &lt;class&gt;Test.php

</pre>

psr-4準拠として、namespaceは名前空間のディレクトリ名。もちろんいくらあっても構わない。
単体テスト用に testsディレクトリを用意して、そこにphpunitのTestCaseを作っていく模様。

### プロジェクト

パッケージを使う側（`composer install`する側）

<pre>
&lt;root&gt;/
    composer.json
    composer.lock
    &lt;vendor&gt;/
        autoload.php
        &lt;composer&gt;/
        &lt;any packages&gt;/
        ...
</pre>

vendor下とcomposer.lockは`composer install` 後にできる。

## composer.json の書式

非常に簡単な例。

### プロジェクト

こちらは依存パッケージを読み込むための定義を書いていく。

``` composer.json
{
    "name": "<vendor>/<project_name>",
    "description": "Composer sample project",
    "authors": [
        {
            "name": "<author>",
            "email": "<mail@mail.com>"
        }
    ],
    "require": {
        "nuuu/muuu": "^1.0"  
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "ssh://user@localhost/var/git/repos/nuuu_muuu.git"
        }
    ]
}
``` 

nuuu/muuuパッケージが必要ですよ、ということと vcsとしてsshのnuuu_muuu.gitリモートリポジトリも使ってね、という設定を主に書いている。
でも、例えばリポジトリが複数（一つ追加しただけでもPackagistと2つになる）になった場合、どのパッケージがどこのリポジトリにいる、とかってどうやって理解してるんだろうか。。。

### パッケージ

``` composer.json
{
    "name": "<vendor>/<package_name>",
    "description": "<package description>",
    "type": "library",
    "version": "1.0.0",
    "authors": [
        {
            "name": "<author>",
            "email": "<mail@mail.com>"
        }
    ],
    "autoload": {
        "psr-4": {"<NamespacePrefix>\\": "src/"}
    },
    "require": {
        "phpunit/phpunit": "*"
    }
}
```
nameについては &lt;vendor&gt;/&lt;package_name&gt; と / 区切りで書く必要がある。
autoload について、 psr-4 に従いディレクトリ構成から名前空間及びクラス名を解決する際に、特定のパスを特定の名前空間にマップできるらしい。
この例の場合だと src/ 以下のディレクトリを &lt;NamespacePrefix&gt;\ という名前空間から始まるクラス名に置き換えている。
したがって、例えば、 NamespacePrefixをNuuu とすれば、 src/Muuu/Uuuu.php は Nuuu\Muuu\のUuuuクラスとなる。
コメントでご指摘があったとおりで、この他にもpsr-4の規約に則った書き方が可能。

## 呼び出し

`vendor/autoload.php`を読み込めば使える。（これがやりたいがための、ね）
Uuuu.phpに static な sayHello()がいたとして。。。

```
require_once(__DIR__ . '/vendor/autoload.php');

use Nuuu\Muuu\Uuuu;

Uuuu::sayHello();

```

## サイクル

諸々準備ができたらあとはこんな感じで開発していくのかね。

1. パッケージを作ってタグをつける(`git tag vX.X.X`) v を頭につけないとうまく認識してくれなかった。
1. `git push origin --tags` などしてリモートリポジトリに上げる
1. プロジェクト側で `composer install`して取り込む（二回目移行は `composer update`すると良いらしい）
1. パッケージを活用した開発を行う
1. パッケージに機能拡張などをしたい場合はまたパッケージをいじる
1. 最初に戻る

## パッケージのテスト

パッケージの`composer.json`にphpunit/phpunitをrequireしてやると、パッケージのvendorディレクトリができるので、そのなかのautoload.phpを読み込んでphpunitにてテストすると良いらしい。このとき、`.gitignore`に/vendor/を入れておけば自分のコードだけがリポジトリに入る。

## まとめ

これでlaravelさんにcomposer経由で自分とこのパッケージ（ライブラリ）を持ってくることができそう。
composerって最初は「なんぞやね？」と思ったけど、使ってみればあぁなるほど、みたいな感じで。
他に沢山機能もあるようだけど、とりあえず自作パッケージの管理とその利用、という意味ではこれで目的は果たせそう。