web-dev-qa-db-ja.com

Laravel:本番データの移行とシード

私のアプリケーションが機能するには、事前に登録されたデータセットが必要です。そのため、アプリケーションをセットアップするときにそれらをデータベースに挿入する必要があります。

Laravel は2つのメカニズムを提案します:

  • データベースの移行 "これにより、チームはデータベーススキーマを変更し、現在のスキーマ状態を最新の状態に保つことができます。"
  • データベースのシード "Laravelには、シードクラスを使用してデータベースにテストデータをシードする簡単な方法も含まれています。"

私がこの説明を読んだとき、これらの解決策はどれも適合していないようです。

同様の質問が stackoverflowで尋ねられましたanswered です。答えは、データベースシーダーを使用して、現在の環境を検出することでデータベースにデータを入力することを提案します。

<?php

class DatabaseSeeder extends Seeder {

    public function run()
    {
            Eloquent::unguard();

            if (App::environment() === 'production')
            {
                $this->call('ProductionSeeder');
            }
            else
            {
                $this->call('StagingSeeder');
            }
    }

}

もちろん、このソリューションは機能します。しかし、シーダーを使用してデータを挿入すると、移行メカニズム(データベースのアップグレード、ロールバックなど)によって提供されるすべての利点が失われるため、これが正しい方法であるかどうかはわかりません。

この場合のベストプラクティスを知りたいです。

39
gontard

Laravelの開発は自由に関するものです。したがって、実稼働データベースをシードし、DatabaseSeederが最適な場所であると考える必要がある場合は、どうしてですか。

わかりました。シーダーは主にテストデータで使用されますが、一部のユーザーはそのまま使用します。

この重要な種は、移行の一部として見えます。これは、データベーステーブルとartisan migrateは、アプリケーションの新しいバージョンをデプロイするたびに実行されるので、

php artisan migrate:make seed_models_table

そして、その中に種苗を作成します:

public function up()
{
    $models = array(
        array('name' => '...'),
    );

    DB::table('models')->insert($models);
}

私はこれに対する正しい答えが何であるかと疑問に思うことがよくあります。個人的には、シードを使用してデータベース内の必要な行にデータを入力することは避けてください。すでに存在するものにデータを入力しないようにするために、条件付きロジックの負荷をかける必要があります。 (データの削除と再作成はveryがお勧めできません。キーの不一致が発生する可能性があり、カスケード削除を使用している場合、データベースの負荷を誤って消去してしまう可能性があります!;-)

行の「シード」を移行スクリプトに入れますが、データはロールアウトプロセスの一部としてそこに存在する必要があります。

Eloquentモデルの代わりにDBクラスを使用してこのデータを設定する必要があることに注意してください。クラス構造は時間とともに変化し、データベースを最初から再作成できなくなります(履歴を書き換えたり、移行ファイルを変更したりすることなく、悪いことだと思います。)

私はこのようなものに行く傾向があります:

public function up()
{
    DB::beginTransaction();

    Schema::create(
        'town',
        function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        }
    );

    DB::table('town')
        ->insert(
            array(
                array('London'),
                array('Paris'),
                array('New York')
            )
        );

    Schema::create(
        'location',
        function (Blueprint $table) {
            $table->increments('id');
            $table->integer('town_id')->unsigned()->index();
            $table->float('lat');
            $table->float('long');
            $table->timestamps();

            $table->foreign('town_id')->references('id')->on('town')->onDelete('cascade');
        }
    );

    DB::commit();
}

これにより、最初に作成するときにタウンテーブルを簡単に「シード」することができ、実行時にテーブルに追加されても干渉しません。

29
Dan B

これは私が本番で使用するものです。

各展開で移行を実行するため

artisan migrate

シーダーを作成し(後で簡単にアクセスできるようにシードデータを移行しないようにするため)、そのシーダーを移行とともに実行します

class YourTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {    
        //migrate your table // Example
        Schema::create('test_table', function(Blueprint $table)
        {
            $table->increments('id');
            $table->timestamps();
            $table->softDeletes();
        });

        //seed this table
        $seeder = new YourTableSeeder();
        $seeder->run();
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::drop('test_table');
    }
}

新しいインストールで2回実行することを避けるために、このseed呼び出しをseeds/DatabaseSeeder.phpに追加しません。

2
Manpreet