LaravelでCSVのインポート時のバリデーションをFromRequestで完結する方法

外部からデータを入れる際のゲートとしてFormRequestにまとめたかった
FormRequestのバリデーション前にCSVを取り込んでパラメータに加えて上げればうまくできた。

//実装例

class ProductRequest extends FormRequest
{

    //バリデーション実行まえにCSVを読み込んでパラメータにセットする。
    protected function prepareForValidation()
    {
        //既存のパラメータを取得しておく
        $params = $this->all();

        //アップロードファイルからエンコードを推定
        $upload = $this->file('csv');
        $detectEncoding = mb_detect_encoding($upload->getContent(), ['SJIS-win', 'SJIS', 'UTF-8'], true);

        //SplFileObjectにしてから読み込んで行く(ExcelCSVのセル内改行など処理etc)
        $csv = new \SplFileObject($upload->path());
        $csv->setFlags(
            \SplFileObject::READ_CSV |
            \SplFileObject::READ_AHEAD |
            \SplFileObject::SKIP_EMPTY |
            \SplFileObject::DROP_NEW_LINE
        );
        $collection = collect();
        foreach ($csv as $value) {
            $collection->add(mb_convert_encoding($value, "UTF-8", $detectEncoding));
        }
        
        //読み込んだデータからパラメータをセット
        $params['header'] = $collection->shift();
        $params['data'] = [];
        $headerNames = ['id','name','price'];
        foreach($collection as $idx1 => $row){
            foreach ($headerNames as $idx2 => $name) {
                $params['data'][$idx1][$name] = $row[$idx2];
            }
        };
        $this->merge($params);
    }


    public function rules(): array
    {
        if (request()->method == Request::METHOD_GET) {
            $rules = [];
        } else {
            $rules = [
                'csv' => ['required', 'mimes:csv', 'mimetypes:text/plain,text/csv'],
                'header' => ['required', 'regex:/^id,name,price$/'],
                'data.*.id' => ['required'],
                'data.*.name'=>['required'],
                'data.*.price'=>['required'],
            ];
        }
        return $rules;
    }

    public function attributes()
    {
        return [
            'csv' => 'CSVファイル',
            'header' => 'ヘッダー行',
            'data.*.id' => '商品ID',
            'data.*.name'=>'商品名',
            'data.*.price'=>'価格',
        ];
    }

}