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に限定されていない
またブラッシュアップできたらこの記事に書き直すわ。
今回の環境
Laravel8
php8
Vue2
Vuetify2
参考文献
ちょっとわかりにくかったがこの記事を参考にして行った。
Laravel-ExcelでCSVインポートを行う