Posted at

laravel-csv-seederを使ってseedデータを登録する(そしてcreate or updateしたい)

More than 1 year has passed since last update.


概要


  • Laravelを利用していて初期データ(マスターデータ)をDBに登録する際に、以下の要件を満たす必要がありました。


    • そこそこの量のマスターデータをcsvで作ってDBに初期登録する

    • マスターデータはレコードの追加や内容の更新が発生する



  • そこで、laravel-csv-seederを利用して実現したのでその時のメモになります。


laravel-csv-seeder


  • laravel-csv-seeder

  • csvファイルをseederの仕組みでいい感じに登録してくれます。


使い方



  • こちらをみていただけるとわかると思いますが、CsvSeederクラスをextendsしたSeederクラスをつくり実装します。


    • テーブル名と用意したcsvファイルをパスで指定するだけです。



use Flynsarmy\CsvSeeder\CsvSeeder;

class HogeHogeMasterTableSeeder extends CsvSeeder

public function __construct()
{
$this->table = 'hogehoge_master';
$this->filename = base_path().'/database/seeds/csvs/hogehoge_master.csv';
}

public function run()
{
DB::disableQueryLog();
DB::table($this->table)->truncate();
parent::run();
}
}


  • あとはDatabaseSeederクラスに実行するSeedのクラスを指定して実行するだけです。

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/

public function run()
{
$this->call(HogeHogeMasterTableSeeder::class);
}
}


  • コマンドからSeed実行

 php artisan db:seed


Truncateしたくない


  • 上記の例だとrunするたびにテーブルをtruncateする処理になっています。

  • 対象のテーブルが単独でいるだけなら問題ないですが、外部参照とかで参照されているとTruncate出来なくてエラ-になります。


    • Truncateじゃなくてレコードがなければinsert、あればupdateするようにしたいです。




insert処理している箇所をoverrideする


  • laravel-csv-seederさんには現状ではそのような機能はないようなので、多少強引ですがメソッドをoverrideして拡張しちゃいます。

  • CsvSeederクラスのinsertメソッドで追加処理しているのでこのメソッドをoverrideします。


    • 引数の$seedDataにはinsertするデータがarrayで渡ってくるので1レコードづつチェックしてinsert or updateするようにします。

    • 下記の例ではidカラムがユニーク制約になっている前提です。



<?php

namespace Database\seeds;

use Flynsarmy\CsvSeeder\CsvSeeder;

class MasterTableSeeder extends CsvSeeder
{

/**
* Run the database seeds.
*
* @return void
*/

public function run()
{
\DB::disableQueryLog();
parent::run();
}

/**
* override method
*
*/

public function insert( array $seedData )
{
foreach($seedData as $seed){
try {
if ( is_null(\DB::table($this->table)->where('id', $seed['id'])->first()) ){
//insert
\DB::table($this->table)->insert($seed);
}else{
//update
\DB::table($this->table)->where('id', $seed['id'])->update($seed);
}
} catch (\Exception $e) {
\Log::error("CSV insert failed: " . $e->getMessage() . " - CSV " . $this->filename);
return FALSE;
}
}
return TRUE;
}


  • 各Seedクラスはこちらのクラスをextendsするように変更します

class HogeHogeMasterTableSeeder extends MasterTableSeeder

public function __construct()
{
$this->table = 'hogehoge_master';
$this->filename = base_path().'/database/seeds/csvs/hogehoge_master.csv';
}
}


まとめ


  • 多少強引でしたが冪等性が確保される状態にすることは出来ました。

  • マスターデータなんだから最初の1回だけ実行すればOKじゃんとかは言わないで下さい。。