Help us understand the problem. What is going on with this article?

laravel-csv-seederを使ってseedデータを登録する(そしてcreate or 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じゃんとかは言わないで下さい。。
myoshioka
フリーランスとしてソフトウェアエンジニアをやっています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away