Packagistに登録するのはもう怖くない


ある日のことなんですが、無性にPHPでプログラミングしたくなった日がありまして、PSRとかComposerとかCIとかの勉強を兼ねてライブラリを作り、Packagistに登録までやってみたので、その時の手順を記します。

## 概要

1. composer.jsonを作る
- ライブラリを作る
- Githubに上げる
- Travis CIと連携させる
- Packagistと連携させる
- GithubのサービスフックにPackagistを登録する


## 事前条件

- php5.6を使いました
- composerをインストールしておいてください。
- gitをインストールしておいてください。
- Githubのアカウントを作っておいてください。
- Githubにpush出来るように鍵の設定などを行っておいてください。
- Travis CIのアカウントを作っておいてください（Githubのアカウントでログインします）
- Packagistのアカウントを作っておいてください（Githubのアカウントでログインします）


## 手順

### composer.jsonを作る

ライブラリのルートになるディレクトリで、`composer init` コマンドを実行してcomposer.jsonを生成します。
コマンドを実行すると、設定値について質問してくるので、入力していくと対話形式で設定していけるのですが、後でcomposer.jsonを直接編集できるので、デフォルト値のままENTERしてしまってもいいです。


ちなみに最初の質問で
`Package name (<vendor>/<name>)`と表示されますが、`<vendor>`はgithubのアカウント名、`<name>`はgithubのrepository名が対応しています（ライブラリ名になります）。


### composer.jsonの編集

上記で作成した、composer.jsonをエディタで開いて以下のように編集します。


```
{
    "name": "niikunihiro/collection",
    "description": "Array Functions Wrapper",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Nii Kunihiro",
            "email": "nii.kunihiro@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "require-dev": {
        "phpunit/phpunit": "5.1.*"
    },
    "autoload": {
        "psr-4": {
            "Collection\\": "src/",
            "CollectionTest\\": "tests/"
        }
    }
}
```

オートロードはPSR-4に準拠させるので、`autoload`に`psr-4`を指定し、
テストで`phpunit`を使うので、`require-dev`で指定しています。

### githubにコミットする

gitbubにリポジトリを作成します。

コマンド例

`git init`
`git remote add origin git@github.com:niikunihiro/collection.git`
`git pull origin master`

composer.jsonをコミットしてpushします。

`git add composer.json`
`git commit -m 'first message'`
`git push origin master`

### ライブラリの作成


プロジェクト直下にtestsディレクトリを作成します。
`mkdir tests`

composerでphpunitをインストールします
`composer update`

インストールに成功したらバージョンを確認しときます
`vendor/bin/phpunit --version`


phpunit.xml.distをライブラリのルートディレクトリに作成します。

```phpunit.xml.dist
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="tests/bootstrap.php"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false">
    <testsuites>
        <testsuite name="Collection Test Suite">
            <directory suffix="Test.php">./tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">./src/</directory>
        </whitelist>
    </filter>
</phpunit>
```

tests/bootstrap.phpをライブラリのルートディレクトリに作成します。

```tests/bootstrap.php
<?php
error_reporting(E_ALL | E_STRICT);
require __DIR__ . '/../vendor/autoload.php';
```

phpunitコマンドを実行して、テストがないぜというメッセージを確認します。
`vendor/bin/phpunit`



### プロダクトコード（ダミー）の作成

プロダクトコードの`src`ディレクトリを作成します

`mkdir src`

プロダクトコードを作成します。とりあえずテストを通すまではデータは決めうちです。

```src/Collection.php
<?php

namespace Collection;

use Closure;

class Collection {

    private $items;

    public function __construct(array $items)
    {
        $this->items = $items;
    }

    public function select(Closure $callback, $flag = 0)
    {
        return $this;
    }

    public function map(Closure $callback)
    {
        return $this;
    }

    public function all()
    {
        return [120, 20, 22];
    }
}
```

### テストコードを作成

```tests/CollectionTest.php
<?php

namespace CollectionTest;

use Collection\Collection;

/**
 * Class CollectionTest
 * @package CollectionTest
 */
class CollectionTest extends \PHPUnit_Framework_TestCase {
    
    /**
     * @test
     */
    public function 配列の要素を10以上のものに絞り込んで2倍した配列を返す()
    {
        $data       = [1, 2, 4, 60, 8, 10, 11];
        $expected   = [120, 20, 22];
        $collection = new Collection($data);
        $actual     = $collection->select(function ($item) {
            return $item >= 10;
        })->map(function ($item) {
            return $item * 2;
        })->all();
        $this->assertEquals($expected, $actual);
    }
}
```

### プロダクトコードの実装

プロダクトコードを実装します。

```src/Collection.php
<?php

namespace Collection;

use Closure;

/**
 * Class Collection
 * @package Collection
 */
class Collection {

    private $items;

    public function __construct(array $items)
    {
        $this->items = $items;
    }

    public function select(Closure $callback, $flag = 0)
    {
        $this->items = array_filter($this->items, $callback, $flag);
        return new static($this->items);
    }

    public function map(Closure $callback)
    {
        $this->items = array_map($callback, $this->items);
        return new static($this->items);
    }

    public function all()
    {
        return array_merge($this->items);
    }
}
```

### Githubにpushする

ここまでで作ったコード一式をGithubにpushします。
pushの前にtagをうっとくといいです。
`git tag v1.0.0`


### Travis CIと連携させる

テストコードを作成してるので、Travis CIにログインしてGithubのリポジトリと連携させます。
Profile に Github のリポジトリ一覧がありますので、連携させるリポジトリの \:negative_squared_cross_mark: を \:white_check_mark: に変更します。


<img width="674" alt="travis_ci_setting.png" src="https://qiita-image-store.s3.amazonaws.com/0/10278/37343910-d756-67dd-913f-9f50a70b5bc6.png">



Travis CIでの設定が終わったら、プロジェクト直下に`.travis.yml`を作成してGithubにpushします。

```..travis.yml
language: php
php:
  - 5.6

before_script:
  - composer self-update
  - composer install

script:
  - vendor/bin/phpunit
```

Githubにpushすると、Travis CIでビルドが開始されます。ビルドが完了したらTravis CIからメールがきます。

ビルドすると、build status imageが出来るので、README.mdファイルに追加します。


```README.md
# collection
php array functions wrapper

[![Build Status](https://travis-ci.org/niikunihiro/collection.svg?branch=master)](https://travis-ci.org/niikunihiro/collection)

```

### Packagistに登録する

PackagistにGithubアカウントでログインして、リポジトリを登録します。
Repository URL(Git/Svn_Hg)欄にGithubのアドレスを入力して、Check -> Submitで登録完了です。

![packagist_submit.png](https://qiita-image-store.s3.amazonaws.com/0/10278/ddb62a52-46ee-79c8-b577-6eaf864c409a.png "packagist_submit.png")

### GithubのサービスフックにPackagistを登録する

GithubにpushしたらPackagistにも連携されるようにします。

PackagistのProfileページからAPI Tokenを取得します。
GithubのリポジトリのSettingsページから Integrations & services ページに移動して、User欄とToken欄を埋めて登録します。Domain欄はデフォルトのままでいいので空欄にします。
次にGithubにコミットしたときにPackagistにも連携されている事が確認できます。

以上です。