LoginSignup
0
1

LaravelでCSVファイルをインポート(maatwebsite/excel)

Posted at

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.phpHeading Row Formatterの部分をnoneにするとうまくいきました。

'heading_row'  => [
    'formatter' => 'none',
],

以上、誰かの参考になれれば幸いです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1