Laravel6 の LazyCollection で CSV を読み込んでデータベースに保存する

Laravel6のLazyCollectionを使ってみたくなったので、試してみます。

ミスなどありましたらご指摘お願いいたします。

#前提
- [こちら](https://hogehoge.tk/personal/generator/)のサービスで名前と生年月日でcsvを作成しました。
max5000件だったので、とりあえず5000件使います。

- テーブル`userinfo`に`id`と`name`と`birthday`だけを持つ簡単なもの

| id       |       name |    birthday    |
|:-----------------|------------------:|:------------------:|

#csvを読み込む

ルーティング

```php:web.php
//csv送信用view
Route::view('/','form')->name('csv');
Route::post('/','CsvController@import');
```

コントローラー
文字コード変換処理を入れていますが、不要なら、保存するだけ
保存しなくていい場合ここはスキップでいいと思います。
`view`の`form`に`enctype="multipart/form-data"`を忘れないように

バリデーションなどは省いています。

```html:file.blade.php
<form action="{{ route('csv') }}" method="post" enctype="multipart/form-data">
<input type="file" name="upload_file">
<input type="submit" value="送信する">
</form>
```

```php:CsvController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use App\UserInfo;

class CsvController extends Controller
{
    public function import(Request $request)
    {
        $content = File::get($request->file('upload_file');
        /* 順番で自動検出し、UTF-8に変換 */
        $content = mb_convert_encoding($content, "UTF-8", "sjis-win, JIS, eucjp-win");
        $result = Storage::put('datas.csv', $content);

    }
}

```

#LazyCollectionをつかう

`import`にそのまま書いていくことにします。
下記のように`dd()`で一度画面に出力してみます。


```php:CsvController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use App\UserInfo;
use Illuminate\Support\LazyCollection;//追加

class CsvController extends Controller
{
    public function import(Request $request)
    {
        $content = File::get($request->file('upload_file');
        /* 順番で自動検出し、UTF-8に変換 */
        $content = mb_convert_encoding($content, "UTF-8", "UTF-8, sjis-win, JIS, eucjp-win");
        $result = Storage::put('datas.csv', $content);

        //ここから追加
        LazyCollection::make(function () {
            $filePath = storage_path('app/datas.csv');
            $file = new \SplFileObject($filePath);
            $file->setFlags(\SplFileObject::READ_CSV);

            foreach ($file as $lines) {
                yield $lines;
            }
        })
            ->skip(1)//ヘッダー行をスキップ
            ->chunk(1000)//分割
            ->each(function ($lines) {
                dd($lines);
            });
    }
}

```
このように`chunk`で分割された1000行分が出力されました
![SC0.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174757/0e64772c-d216-de37-6b2a-26025d63fe4c.jpeg)

あとはループして、insertします

```php:CsvController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use App\UserInfo;
use Illuminate\Support\LazyCollection;

class CsvController extends Controller
{
    public function import(Request $request)
    {
        $content = File::get($request->file('upload_file');
        /* 順番で自動検出し、UTF-8に変換 */
        $content = mb_convert_encoding($content, "UTF-8", "UTF-8, sjis-win, JIS, eucjp-win");
        $result = Storage::put('datas.csv', $content);

        
        LazyCollection::make(function () {
            $filePath = storage_path('app/datas.csv');
            $file = new \SplFileObject($filePath);
            $file->setFlags(\SplFileObject::READ_CSV);

            foreach ($file as $lines) {
                yield $lines;
            }
        })
            ->skip(1)//ヘッダー行をスキップ
            ->chunk(1000)//分割
            ->each(function ($lines) {
                $data = [];
                foreach($lines as $line){
                    $data[] = [
                        'name' => $line[0]
                        'birthday' => $line[1]
                    ];
                }
                //バルクインサート
                UserInfo::insert($data);
            });
    }
}

```


メモリ監視していないので消費量分からないですが、とりあえず使ってみました。
ミスやより良い方法がありましたら教えて頂けますと幸いです。