PHPの配列操作がめんどいのでRxPHPを導入する

# RxPHPを使ってみようと思った経緯
PHPで複雑な配列操作をしていると辛くなった事があったので、良い解決策がないかと思って[RxPHP](https://github.com/ReactiveX/RxPHP)調べたらいい感じにかけそうだったので使ってみた

## PHPの配列操作はめんどくさい
PHPには配列操作用にarray_map、array_filter、array_reduceなど
配列が操作できる関数が色々ある
基本的にコールバック関数を使って操作する

### 配列操作の例 (3文字よりでかい単語だけ抽出して文字の合計を算出)
```php:例1(一旦変数に渡す)
$languages = ['PHP', 'PYTHON', 'RUBY', 'GOLANG'];

$lengths = array_map(
    function ($lang) { return str_len($lang) },
    $languages
);

$filterd = array_filter(
    $lengths,
    function ($length) { return $length > 3 }
);

$sum = array_reduce(
    $filtered,
    function ($x, $y) { return $x + $y }
);
```
これだといちいち変数に入れるんめんどい

```php:例2(処理をネストする)
$languages = ['PHP', 'PYTHON', 'RUBY', 'GOLANG'];

$sum = array_reduce(
    array_filter(
        array_map(
            function ($lang) { return str_len($lang) },
            $languages
        ),
        function ($length) { return $length > 3 }
    ),
    function ($x, $y) {
        return $x + $y
    }
);
```
ネストして見にくいしコードの修正がしにくくてめんどい

## Javascriptみたいにメソッドチェーンで書きたいと思ってたらRxPHPで書けそうだった
### JSで書いた場合
```javascript
const languages = ['PHP', 'PYTHON', 'RUBY', 'GOLANG'];
const sum = languages
.map(lang => lang.length)
.filter(length => length > 3)
.reduce((x, y) => x + y);
```
JSみたいにメソッドチェーンで書けると見やすいし、いちいち変数を作らなくていい

# RxPHPを使ってみる

RxPHPはReactive Programmingをするためのライブラリ[ReactiveX](http://reactivex.io/)らしく、オブザーバーパターンとかイテレーターパターンとか使ってるみたい
配列以外にも、イベント処理とか非同期処理にも使えるけど、PHPではライブラリ(ReactPHPとか)入れないと使えないので、普通は配列以外では使わんかなと思うので、とりあえずややこしい話はどうでもいい

## RxPHPの構成要素
Observable, Observer, Operatorぐらい分かっとけば配列操作では困らないと思う

### Observable
データをぶん投げるやつ

### Observer
データをObservableから受け取って処理する

### Operator
Observerに渡す前にデータを加工できる
PHP関数のarray_map, array_filter, array_reduceみたいなやつ
他色々処理ができる
何種類あるかは知らん

### Stream
ObservableからObserverまでの流れをStreamと言ってるみたい

## RxPHPでコードを書いてみる
### インストール
```bash
composer require reactivex/rxphp
```

### さっきの例と同じコードをかく
```php:RxPHP
use Rx\Observable;
use Rx\Scheduler;
use Rx\Scheduler\ImmediateScheduler;

// スケジューラーの設定
$immediateScheduler = new ImmediateScheduler();
Scheduler::setDefaultFactory(function () use ($immediateScheduler) {
    return $immediateScheduler;
});

// 配列処理
const languages = ['PHP', 'PYTHON', 'RUBY', 'GOLANG'];
Observable::fromArray(languages) // Observable
    ->map(function ($lang) { // Operator
        return str_len($lang);
    })
    ->filter(function ($length) { // Operator
        return $length > 3;
    })
    ->reduce(function ($x, $y) { // Operator
        return $x + $y;
    })
    ->subscribe( //Observer
        function ($sum) {
            print("合計は$sum")
        },
        // どっかでエラーが出たら発火
        function (\Exception $ex) {
            print('失敗したよ')
        },
        // 投げたデータの処理が全て完了したら発火
        function () {
            print('完了したよ')
        });
```

Schedulerを設定しないと怒られたので設定
Schedulerは、どう実行するのか(スレッド分けたり、処理の順番変えたり)決められるが、PHPはライブラリ入れんとスレッド分けれんし基本逐次処理なので即座に実行してくれるimmediateSchedulerを設定する
なんでimmediateSchedulerがデフォルト設定じゃないんかな？
設定しなくてもいい気がするのでなんかミスってるかも

Rx\ObservableのfromArrayメソッドで配列を投げる
map・filter・reduceメソッドがOperatorにあたる
subscribeがObserverにあたって、データ受け取り時、処理エラー時、完了時にそれぞれ処理が書ける


#まとめ
この記事では、RxPHP使った方がコード量は多くなったが、複雑な配列処理をめっちゃ書くプロジェクトがあれば、効力(可読性とか保守性とか)を発揮するはず
単純な処理しかない場合は、既存の関数で十分かなと思う