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から登録
//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');
とすれば、西暦が抜けてる日付なんかでもいい感じにデータベースに登録ができる。
ちょっとわかりにくかったがこの記事を参考にして行った。
文字化け対策
MicrosoftのExcel上で文字化けせずに開き、なおかつUTF-8としてLaravelに認識させたければ、エディターでUTF-8 with BOM
を指定して保存すればいい。
VS Codeなら、
右下の文字コードの表示をクリックする。(この画像はすでにUTF-8 with BOM
で保存できている状態)
UTF-8 with BOM
を選んであげればいい。
- 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 エンコードを正しく識別するのに役立ちます。
- Microsoft Excel の動作:
- Microsoft Excelは、CSVファイルを開くときにエンコーディングを自動的に検出しますが、BOMがない場合、エンコーディングを正しく認識できないことがあります。その結果、文字化けが発生する可能性があります。しかし、BOMが付いていると、ExcelはファイルがUTF-8エンコーディングであることを認識し、文字化けを防ぐことができます。
- Laravel-Excel の動作:
- Laravel-Excelは、エンコーディングを明示的に指定しない限り、ファイルのエンコーディングを自動的に検出します。BOMが付いていると、Laravel-Excelもまた、ファイルがUTF-8エンコーディングであることを正しく認識し、それに応じて処理を行います。
懸念点
- このままだと成功したか失敗したかもわからない
- バリデーションもかかってない
- 文字コードが合わないとどうなるか不明
- アップロード可能なファイルがCSVに限定されていない
またブラッシュアップできたらこの記事に書き直すわ。
今回の環境
Laravel8
php8
Vue2
Vuetify2
参考文献
ちょっとわかりにくかったがこの記事を参考にして行った。
Laravel-ExcelでCSVインポートを行う