LaravelでExcelを操作するための「Laravel Excel」というパッケージがありあます。
今回はそれを利用してCSVファイルをデータベースへ簡単にインポートする方法をご紹介します。
CSVを使ったデータの一括登録にとても便利です!
Laravel ExcelでCSVをインポート
[Laravel Excel]の基本的な使い方は、パッケージを配布している公式サイトに書いてありますので参考にしてください。
パッケージのインストール
いつもの如、Composerを使って[Laravel Excel]パッケージをインストールします。
composer require maatwebsite/excel
Laravelのバージョンによっては、[config/app.php]内のプロバイダーとエイリアスの登録は不要になります。
最後にartisanで[vendor:publish]を実行すれば完了です。
php artisan vendor:publish
これでconfigディレクトリの中に[excel.php]という設定ファイルが入ります。
後程使います。
CSVデータを1行ずつ登録
今回の場合は、CSVデータをデータベースに一括登録しますので、コントローラー側でストレージディレクトリに保存しているCSVデータを1行ずつ読み込んでインサートします。
その際、同じものがあれば更新、なければ新規登録を行います。
登録先のテーブル名はposts(モデル名はPost)とします。
CSVの内容はブログによくある記事のタイトルや内容を想像してください。
設定ファイルの変更
今回の例ではCSVファイルのサイズが巨大なため、以下を変更しています。
お好みで変更してください。
・・・
'settings' => [
'memoryCacheSize' => '32MB',
'cacheTime' => 600
],
・・・
また、この記事を読まれているということは、日本語を使っていると思いますので、文字化けしないように入出力の文字コードを変更する必要があるかもしれません。
デフォルトはUTF-8なので、日本語ならShift-JISかな?
著者はUTF-8に変換済みのCSVファイルを使いますのでこのままです。
・・・
'encoding' => [
'input' => 'UTF-8',
'output' => 'UTF-8'
],
・・・
最後に、ここが1番重要です!
CSVを1行ずつ読み込む際に、CSVのヘッダ(1行目)をキーとして使わないようにしましょう。
CSVファイルの1行目と登録するテーブルのフィールド名が一致していれば変更の必要はなく、もっと簡単になりますが、日本に住んでいる限りそんなに都合の良いデータがあるはずもなく…。
ってことで、[heading]を[false]にして1行目を無視します。
'heading' => 'false',
Modelにfillableをセットする
上記の通り、CSVの1行目を使いませんので、Postモデルの[$fillable]にCSVと一致するフィールド名を登録しておきます。
// 例)
protected $fillable = ['post_id', 'title', 'body', 'category', 'tags', 'status' … ];
Controllerで差分登録
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use Excel;class CsvController extends Controller
{
public function __construct(Post $post)
{
$this->post = $post;
}
public function import()
{
$fields = $this->post->getFillable();
$reader = Excel::load(storage_path('csv/data.csv'));
$rows = $reader->toArray();
foreach ($rows as $row){
$id = $row[0];
$record = $this->post->firstOrNew(['post_id' => $id]);
foreach ($row as $key => $value) {
$colmun = $fields[$key];
$record->$colmun = $value;
}
$record->save();
}
}
}
解説
まずは、[use]でLaravel Excelを宣言して、CSV一括登録用の関数を作成します。
Excel::load(storage_path('csv/data.csv'));
で[/storage/csv/data.csv]のCSVを読み込み、
$reader->toArray();
で配列に変換し、行数分ループを回します。
[firstOrNew()]でデータの存在を確認し、なければオブジェクトを生成します。
Postモデルの[$fillable]の値をキーにセットして、[save()]で登録します。
今回は差分登録するために[save()]を使ってデータを登録します。
[save()]関数は、データが存在して変更があるならupdate、存在しなければinsertを自動的に行なってくれます。
【番外編】
もしCSVの1行目とテーブルのフィールド名が一致していたら、2つ目のループが不要になり、以下のように書くことができます。
・・・
foreach ($rows as $row){
$id = $row['post_id'];
$record = $this->post->firstOrNew(['post_id' => $id]);
$record->fill($row);
$record->save();
}
・・・・
CSVファイルをアップロードするやり方はこちらを参考に。

次はCSV出力も試してみたいです。
以上、すごく便利ですね。


コメント
コメント一覧 (2件)
[…] 1 share 1 user 1 pocket Laravel ExcelパッケージでCSVデータをDBへ一括登録する方法https://minory.org/laravel-excel-csv.htmlLaravelでExcelを操作するための「Laravel […]
[…] 画面にメッセージを表示する、またログを出力するために少し手を加えてます。 ※詳細は下記のコントローラー内のimport()を参照 Laravel ExcelパッケージでCSVデータをDBへ一括登録する方法 […]