LaravelでCSVファイルのインポート機能を作成しようと思い、maatwebsite/excelというライブラリを使ってみました。
メモとして使用例を残しておきます。
インストール
公式に則って行います。
https://docs.laravel-excel.com/3.1/getting-started/installation.html
composer require maatwebsite/excel
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
config/excel.php
というファイルが作成されます。
前提
今回アップロードしたいCSVのサンプル
企業名,郵便番号,住所,電話番号,代表者名,担当者名,備考
テスト02株式会社,2203456,埼玉県上尾市井戸木,090-4736-0924,佐藤,中島,テストです
上記の1行目をタイトルとして認識させ、2行目以降をデータとして挿入したいという要件です。
Importクラスの作成
app/Imports/CompaniesImport.phpを作成
namespace App\Imports;
use App\Models\Company;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class CompaniesImport implements ToModel, WithHeadingRow
{
public function model(array $row)
{
return new Company([
'name' => $row['企業名'],
'post_code' => $row['郵便番号'],
'address' => $row['住所'],
'tel' => $row['電話番号'],
'ceo_name' => $row['代表者名'],
'responsible_person_name' => $row['担当者名'],
'note' => $row['備考'],
]);
}
}
WithHeadingRow
を使用すると、最初の行をタイトルとして認識してくれるようです。
他にも色々使い方があるようなので、公式をご確認ください。
https://docs.laravel-excel.com/3.1/imports/heading-row.html
コントローラーの作成
app/Http/Controllers/CompanyController.php
// メソッドだけ抜き取り
public function import(Request $request)
{
$file = $request->file('file');
Excel::import(new CompaniesImport, $file);
return redirect()
->route('company.index')
->with('message', 'データが正常にインポートされました');
}
ルーティング
web.php
Route::post('/company/import', [CompanyController::class, 'import'])->name('company.import');
フロント(Blade)
resources/views/company/create.blade.php
<form action="{{ route('company.import') }}" method="post" enctype="multipart/form-data" class="flex flex-col md:flex-row items-center gap-2 justify-end w-full md:w-3/4 lg:w-2/5">
@csrf
<div class="w-full flex-1">
<input type="file" name="file" id="file" accept=".csv,.xlsx,.xls" class="w-full text-gray-500 font-medium text-sm bg-gray-100 file:cursor-pointer cursor-pointer file:border-0 file:py-2 file:px-4 file:mr-4 file:bg-gray-800 file:hover:bg-gray-700 file:text-white rounded">
</div>
<div class="w-full md:w-44 flex gap-2 justify-end">
<button type="submit" class="focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 border border-gray-300 hover:opacity-80">アップロード</button>
<button type="button" id="clearButton" class="focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-1.5 border border-gray-300 hover:opacity-80">クリア</button>
</div>
</form>
ファイル送信の際には、formタグにenctype="multipart/form-data"
を入れる必要があるので忘れずに。
2つ目のボタン(クリアボタン)は、ファイル選択したけど「やっぱやめた」というとき用のボタンです。
これはJavaScriptで実装しているのですが、今回の内容とはずれるので詳細は割愛します。
最後にImportクラスのWithHeadingRow
で最初の行のタイトルが日本語だとうまくいかなったのですが、config/excel.php
のHeading Row Formatter
の部分をnone
にするとうまくいきました。
'heading_row' => [
'formatter' => 'none',
],
以上、誰かの参考になれれば幸いです。