PHP: Slackにメッセージを投稿するクラス

使い捨てなのでメモ程度に投稿します…。

## 使い方

```php:メッセージを送る
$webhookUrl = 'https://hooks.slack.com/services/...';
$notifier = new SlackNotifier($webhookUrl);
$notifier->text('すみません、デプロイに失敗しました…');
```

<img width="295" alt="Slack 2.png" src="https://qiita-image-store.s3.amazonaws.com/0/889/f476cc04-b965-3673-8fdd-da5343fff0d5.png" class="img-thumbnail">


```php:本番環境の例外を送りつける
$notifier->exception(new RuntimeException('Something wrong'), [
    'host'     => 'www.example.com',
    'url'      => 'http://www.example.com/foo/bar/buz/?foo=1&bar=2',
    'user_ip'  => '192.168.0.1',
    'user_id'  => 123,
    'username' => 'alice',
]);
```

単に例外だけだと対処できないケースがあるので、ユーザIDなども合わせて送れます。

<img width="658" alt="Slack.png" src="https://qiita-image-store.s3.amazonaws.com/0/889/15d86904-b16b-15c6-4f4f-21164f1ea536.png" class="img-thumbnail">

## Slackにメッセージを投稿するクラス

```php:SlackNotifier.php
class SlackNotifier
{
    /** @var string */
    private $webhookUrl;
    /** @var int */
    private $timeout;

    /**
     * @param string $webhookUrl
     * @param int $timeout
     */
    public function __construct($webhookUrl = '', $timeout = 3)
    {
        $this->webhookUrl = $webhookUrl;
        $this->timeout = $timeout;
    }

    /**
     * @param string $text
     * @param array $options
     * @return array
     */
    public function text($text, array $options = [])
    {
        return $this->send(array_merge($options, [
            'text' => $text,
        ]));
    }

    /**
     * @param array $attachment
     * @param array $options
     * @return array
     */
    public function attachment(array $attachment, array $options = [])
    {
        return $this->send(array_merge($options, [
            'text'        => '',
            'attachments' => [$attachment],
        ]));
    }

    /**
     * @param Exception $exception
     * @param array $meta
     * @param array $options
     * @return array
     */
    public function exception(\Exception $exception, array $meta = [], array $options = [])
    {
        return $this->attachment([
            'color'  => 'danger',
            'title'  => sprintf('[%s] %s', get_class($exception), $exception->getMessage()),
            'text'   => strval($exception),
            'fields' => array_map(function ($title, $value) {
                return [
                    'title' => $title,
                    'value' => $value,
                    'short' => true,
                ];
            }, array_keys($meta), array_values($meta))
        ], $options);
    }

    /**
     * @param array $payload
     * @return array
     */
    public function send(array $payload)
    {
        return $this->httpPost(
            $this->webhookUrl,
            ['payload' => json_encode(array_filter($payload))]
        );
    }

    /**
     * @param string $url
     * @param array $data
     * @return array
     */
    private function httpPost($url, $data)
    {
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
        curl_setopt($curl, CURLOPT_HEADER, true);
        $response = curl_exec($curl);
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);
        $body = substr($response, $header_size);
        curl_close($curl);
        return [
            'url'    => $url,
            'data'   => $data,
            'status' => $status,
            'header' => $header,
            'body'   => $body,
        ];
    }
}
```

## 関連

* [PHPでSlackにメッセージをポストするクラスのサンプル - Qiita](http://qiita.com/monhan/items/d95ad6e4e698da9e6593): "SlackのWebhookを利用して、API経由でメッセージをポストする。ささっとPHPで試したい方や、botを作りたい方向け。"