LaravelでExcelを操作するための「Laravel Excel」というパッケージがありあます。
今回はそれを利用してCSVファイルをデータベースへ簡単にインポートする方法をご紹介します。
CSVを使ったデータの一括登録にとても便利です!
Laravel ExcelでCSVをインポート
Laravel Excelの基本的な使い方は公式サイトに書いてありますので参考にしてください。
パッケージのインストール
いつもの如、Composerを使ってパッケージをインストールします。
composer require maatwebsite/excel
著者の場合は、Laravelのバージョンが5.5ですので、config/app.php
内のプロバイダーとエイリアスの登録は不要になります。
最後にLaravelのvendor:publish
コマンドで完了です。
php artisan vendor:publish
これでconfigディレクトリの中にexcel.php
という設定ファイルが入ります。
後程使います。
CSVデータを1行ずつ登録
今回のシチュエーションは、コントローラー側でストレージディレクトリに保存している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を宣言します。
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出力も試してみたいです。
以上、すごく便利ですね。
- Original:https://minory.org/laravel-excel-csv.html
- Source:Minory
- Author:管理者