はじめに
※マジでメモです、すいません。※
この一年でCSVアップロード機能を作る機会が何回かありまして、その度に作り方を思い出す作業をしていたので自分用にメモを残します。
必要なもの
- CSVファイルを受け取るフォーム
- 拡張子などファイルの形式チェック機能
- CSVファイルをローカルに保存する処理
- バリデーション機能
- DBに保存できる形に変換する処理
- DB保存処理
1. CSVファイルを受け取るフォーム(View)
Formタグにenctype="multipart/form-data">
を追加する
<form method="post" action="{{ route('sample.upload_csv') }}" enctype="multipart/form-data">
2. 拡張子などファイルの形式チェック機能(Controller)
※拡張子がcsv
であるかチェック
public function uploadCsv(Request $request)
{
if ($request->hasFile('csvFile')) { // ファイルの存在確認
if($request->csvFile->getClientOriginalExtension() !== 'csv') {
// エラー処理
} else {
...
3. CSVファイルをローカルに保存する処理(Serviceとか)
public function saveStorage($request)
{
$path = '/public/storage/csv/'; // 保存先のパス configとかから取得した方が良さそう
// CSVファイルに一意な名前を付ける
$current_time = date('Y-m-d_H_i'); // 現在時刻
$file_name = Sample::SAMPLE_NAME. '.'. $current_time . '.csv'; // ファイル名
$request->csvFile->storeAs($path, $file_name); // ファイル保存
//保存したCSVファイル内容を取得
$csv = Storage::disk('local')->get($path . $file_name);
4. バリデーション機能(Serviceとか)
CSVファイルの中身を変換しやすい形にする→バリデーションにかける
※今回はバリデーションに関しては割愛
$csv = str_replace(array("\r\n", "\r"), "\n", $csv); // 改行コードを統一
$data = collect(explode("\n", $csv)); //一行ずつコレクションを作成
$header = collect(Sample::SAMPLE_HEADER); // Enumとかからヘッダを取得
5. DBに保存できる形に変換する処理(Serviceとか)
ヘッダ + 一行単位のデータの組み合わせにする
public function combineHeader($data, $header)
{
//返す配列
$csvs = [];
$j = 0; // インデックス用の変数
foreach ($data as $key => $d) {
if ($key == 0) {
continue; // CSVのヘッダをスキップする
} else {
$d = mb_convert_encoding($d, "UTF-8", "SJIS-win"); // 文字コード変換
$ex = explode(",", $d); // csvデータをカンマ区切りに変換
$item = str_replace('', 'null', $ex); // 空文字はnullにする
$csv = []; // ヘッダ + 一行単位のデータを格納
foreach ($header as $key => $h) {
if (strlen($item[$key]) <= 0) {
$csv[$h] = null; // データが無い項目にはnullを格納
} else {
$csv[$h] = $item[$key]; // 対応するヘッダとデータの項目を組み合わせる
}
}
$csvs[$j] = $csv; // ヘッダ + 一行単位のデータを格納
$j++;
}
}
return $csvs;
}
6. DB保存処理(Controllerとか)
流石に↓のまま保存するのはあまり良くはない…(まぁ今回はサンプルなので)
$this->csv_service->saveStorage($request); // そのまんま
一旦上記の処理でCSVファイル取得→DBに保存までは実装できると思います!!!
終わり!!