LaravelとVue.jsを使って、CSVファイルに記載された情報(複数レコード)をデータベースに一括登録する方法を解説。

ライブラリ「Laravel-Excel」

今回は、Customers(顧客)テーブルに複数の顧客を登録することを想定。

Laravel-Excelのインストールと設定ファイル生成

composer require maatwebsite/excel

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

クラスを作成

php artisan make:import CustomerImport

作ったクラスを編集する

ちなみにこんなCSVファイルを読み取ることを想定して今回は作成する。

//CustomerImport.php

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\WithStartRow;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;

use App\Models\Customer;//追記

class CustomerImport implements ToCollection, WithStartRow
{
    /**
    * @param Collection $collection
    */
    public static $startRow = 2; // csvの1行目にヘッダがあるので2行目から取り込む

    public function collection(Collection $rows)
    {
        foreach ($rows as $row) {
            Customer::create([
                'type' => $row[0], // 左から1列目
                'customerName' => $row[1], // 左から2列目
                'dealer' => $row[2], // 左から3列目
            ]);
        }
    }
    public function startRow(): int
    {
        return self::$startRow;
    }    
}

タイムスタンプは勝手に入る。

呼び出せるようにする

コントローラー

<?php
//CustomerController.vue
namespace App\Http\Controllers
use Illuminate\Http\Request;
use Carbon\Carbon;

use App\Models\Customer;
//csv関係
use App\Imports\CustomerImport;//殺菌作ったモデルの読み込み
use Maatwebsite\Excel\Facades\Excel;
use Maatwebsite\Excel\Validators\ValidationException;

public function importCustomerByCsv(Request $request)//(Content $content)
    {
        $file = $request->file;
        // アップロードされたCSVファイル

        try {
            $import = new CustomerImport();
            Excel::import($import, $file);
        } catch (ValidationException $e) {
            Log::alert($e->errors());
        }
    }

api

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\CustomerController;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::post('/customers/import', [CustomerController::class, 'importCustomerByCsv']);

いざ、CSVから登録

CSVファイルを送ることができるフォームを作成する。

//Customer.vue
<template>
    <div>
        <v-file-input v-model="file"></v-file-input>
        <v-btn @click="csvRegister">CSVで一括登録</v-btn>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                file: null
            }
        },
        methods: {
            csvRegister() {
                let formData = new FormData()
                formData.append('file', this.file)
                axios.post('/api/customers/import', formData)
                    .then(response => {
                        console.log(response.data)
                    })
            },
        }
    }
</script>

v-file-inputタグはVuetifyというフレームワークの書き方なので、input type="file"みたいな感じに書き換えてもいい。

いざ、CSVから登録

//Customer.vue
<template>
    <div>
        <v-file-input v-model="file"></v-file-input>
        <v-btn @click="csvRegister">CSVで一括登録</v-btn>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                file: null
            }
        },
        methods: {
            csvRegister() {
                let formData = new FormData()
                formData.append('file', this.file)
                axios.post('/api/customers/import', formData)
                    .then(response => {
                        console.log(response.data)
                    })
            },
        }
    }
</script>

このままだと成功したか失敗したかもわからない。

バリデーションもかかってない。

またブラッシュアップできたらこの記事を書き直すわ。

日付の登録時のフォーマット整形

$日付の入った変数=date('Y-m-d');

とすれば、西暦が抜けてる日付なんかでもいい感じにデータベースに登録ができる。

ちょっとわかりにくかったがこの記事を参考にして行った。

Laravel-ExcelでCSVインポートを行う

文字化け対策

MicrosoftのExcel上で文字化けせずに開き、なおかつUTF-8としてLaravelに認識させたければ、エディターでUTF-8 with BOM を指定して保存すればいい。

VS Codeなら、

右下の文字コードの表示をクリックする。(この画像はすでにUTF-8 with BOM で保存できている状態)


UTF-8 with BOMを選んであげればいい。

  1. UTF-8 と UTF-8 with BOM の違い:
    • UTF-8は、Unicode 文字を1バイトから4バイトのシーケンスでエンコードする方法を提供します。これは、ASCII 文字を含む多くのテキストファイルにとって効率的です。
    • UTF-8 with BOM(Byte Order Mark)は、ファイルが UTF-8 エンコードであることを示す特殊なマーカーをファイルの先頭に含みます。この BOM は、特に Windows のアプリケーションで UTF-8 エンコードを正しく識別するのに役立ちます。
  2. Microsoft Excel の動作:
    • Microsoft Excelは、CSVファイルを開くときにエンコーディングを自動的に検出しますが、BOMがない場合、エンコーディングを正しく認識できないことがあります。その結果、文字化けが発生する可能性があります。しかし、BOMが付いていると、ExcelはファイルがUTF-8エンコーディングであることを認識し、文字化けを防ぐことができます。
  3. Laravel-Excel の動作:
    • Laravel-Excelは、エンコーディングを明示的に指定しない限り、ファイルのエンコーディングを自動的に検出します。BOMが付いていると、Laravel-Excelもまた、ファイルがUTF-8エンコーディングであることを正しく認識し、それに応じて処理を行います。

懸念点

  • このままだと成功したか失敗したかもわからない
  • バリデーションもかかってない
  • 文字コードが合わないとどうなるか不明
  • アップロード可能なファイルがCSVに限定されていない

またブラッシュアップできたらこの記事に書き直すわ。

今回の環境

Laravel8
php8
Vue2
Vuetify2

参考文献

ちょっとわかりにくかったがこの記事を参考にして行った。
Laravel-ExcelでCSVインポートを行う

無制限に質問可能なプログラミングスクール!

万が一転職できない場合は、転職保障全額返金できるコースもあり!!

無制限のメンター質問対応

 

DMMウェブキャンプでプログラミングを学習しませんか?

独学より成長スピードをブーストさせましょう!

 

まずは無料相談から!

おすすめの記事