Laravel学習メモ：コレクション

## 参考

## コレクション

- `Illuminate\Support\Collection`クラス
    - 配列データを操作するためのラッパー
    
    ```php
    $collection = collect(['taylor', 'abigail', null])->map(function (string $name) {
        return strtoupper($name);
    })->reject(function (string $name) {
        return empty($name);
    });
    ```
    
    - 上記の例の場合、元のコレクションは不変ですべてのCollctionメソッドは新しいCollectionインスタンスを返す。
- コレクション生成
    - 指定された配列をもとに`Illuminate\Support\Collection`インスタンスを返す。
    - Eloquentのクエリ結果は常にCollectionインスタンス
- コレクションの拡張
    - コレクションはマクロ化可能で実行時にCollectionクラスへメソッドを追加可能
    - **`macro`**メソッド
        - 呼び出し時に実行するクロージャを引数にとる。
        
        ```php
        use Illuminate\Support\Collection;
        use Illuminate\Support\Str;
        
        // macro化
        Collection::macro('toUpper', function () {
        	  // クロージャ
            return $this->map(function (string $value) {
                return Str::upper($value);
            });
        });
        
        $collection = collect(['first', 'second']);
        
        $upper = $collection->toUpper();
        
        // ['FIRST', 'SECOND']
        ```
        
    - 通常、コレクションマクロは[サービスプロバイダ](https://readouble.com/laravel/10.x/ja/providers.html)の`boot`メソッドで宣言する必要がある
    - この書き方に出会ったことがない…
- 利用可能なメソッド
    - かなり多い。
    - 随時確認。
- メソッド一覧（の中で気になったもの）
    - `chunk()`
        - 指定したサイズで小さなコレクションに分割する
        
        ```php
        $collection = collect([1, 2, 3, 4, 5, 6, 7]);
        $chunks = $collection->chunk(4);
        $chunks->all(); // [[1, 2, 3, 4], [5, 6, 7]]
        ```
        
        - グリッドシステムを操作する時にViewで特に役に立つ
        
        ```php
        @foreach ($products->chunk(3) as $chunk)
            <div class="row">
                @foreach ($chunk as $product)
                    <div class="col-xs-4">{{ $product->name }}</div>
                @endforeach
            </div>
        @endforeach
        ```
        
    - `contains()`
        - コレクションに指定したアイテムが含まれるか判定する
        - クロージャを渡す
        
        ```php
        $collection = collect([1, 2, 3, 4, 5]);
        // 5よりも大きい値を含むか？
        $collection->contains(function (int $value, int $key) {
            return $value > 5;
        });
        // false
        ```
        
        - `contain()`は緩い比較。厳密に比較するなら`containStrict()`
    - `dd()`, `dump()`
        - ddは実行を停止し、dumpは止めない。
    - `duplicates()`
        - 重複値を返す
    - `lazy()`
        - アイテムの配列から新しいレイジーコレクションインスタンスを返す
            - 巨大なデータセットをメモリを抑えて利用できる
    - `only()`
        - コレクションの指定したアイテムだけを返す
        
        ```php
        $collection = collect([
            'product_id' => 1,
            'name' => 'Desk',
            'price' => 100,
            'discount' => false
        ]);
        
        $filtered = $collection->only(['product_id', 'name']);
        
        $filtered->all();
        
        // ['product_id' => 1, 'name' => 'Desk']
        ```
        
    - `plunk()`
        - 指定したキーの全コレクション値を取得する
        
        ```php
        $collection = collect([
            ['product_id' => 'prod-100', 'name' => 'Desk'],
            ['product_id' => 'prod-200', 'name' => 'Chair'],
        ]);
        
        $plucked = $collection->pluck('name');
        
        $plucked->all();
        
        // ['Desk', 'Chair']
        ```
        
        - キー項目の指定も可
        
        ```php
        $plucked = $collection->pluck('name', 'product_id');
        $plucked->all();
        // ['prod-100' => 'Desk', 'prod-200' => 'Chair']
        ```
        
    - `push()`
        - コレクションの最後にアイテムを追加
    - `toArray()`
        - コレクションをPHPの「配列」に変換
        - コレクションの裏の素の配列をそのまま取得したい場合は、代わりに`[all](https://readouble.com/laravel/10.x/ja/collections.html#method-all)`メソッドを使用する
    - `unique()`
        - 重複を除いた全アイテムを返す
    - `values()`
        - キーをリセットして連続した整数にした新しいコレクションを返す
- レイジーコレクション
    - 巨大なデータセットをメモリ使用を抑えて利用する目的
    - PHPジェネレータを利用する
    - アプリケーションで数ギガバイトのログを処理する必要があり、ログを解析するためにLaravelのコレクションメソッドを活用するとしましょう。
        - ファイル全体をメモリへ一度で読み込む代わりに、レイジーコレクションなら毎回ファイルの小さな部分だけをメモリに保持するだけで済みます。
    - 通常のコレクションだと一度にすべてをメモリにロードする必要が生まれる
    - レイジーコレクションを活用すると大幅にメモリ使用量