Laravel移行ファイルへのデータベースの入力


115

私はLaravelを学習しているだけで、usersテーブルを作成する移行ファイルが機能しています。移行の一部としてユーザーレコードを入力しようとしています。

public function up()
{
    Schema::create('users', function($table){

        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();

        DB::table('users')->insert(
            array(
                'email' => 'name@domain.com',
                'verified' => true
            )
        );

    });
}

しかし、実行すると次のエラーが発生しますphp artisan migrate

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist

これは明らかにArtisanがまだテーブルを作成していないためですが、すべてのドキュメントには、移行の一部としてFluent Queryを使用してデータを入力する方法があると記載されているようです。

誰か知ってる?ありがとう!

回答:


215

DB :: insert()をSchema :: create()内に配置しないでください。これは、createメソッドがテーブルの作成を完了してから、データを挿入できるようにするためです。代わりにこれを試してください:

public function up()
{
    // Create the table
    Schema::create('users', function($table){
        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();
    });

    // Insert some stuff
    DB::table('users')->insert(
        array(
            'email' => 'name@domain.com',
            'verified' => true
        )
    );
}

5
複数のデータを挿入する方法は?
Sahbaz

6
SuperMario'sYoshi @私はこのようなものだと思うDB::table('users')->insert([ ['email' => 'taylor@example.com', 'votes' => 0], ['email' => 'dayle@example.com', 'votes' => 0] ]);
Денис

80

私はこれが古い投稿であることを知っていますが、それはグーグル検索で出てくるので、私はここでいくつかの知識を共有したいと思いました。@ erin-geyerは、移行とシードを混在させると頭痛の種になる可能性があることを指摘し、@ justamartinは、展開の一部としてデータを入力したい/必要とする場合があると反論しました。

さらに一歩進んで、たとえばステージングにデプロイしてすべてが順調であることを確認し、同じ結果を確信して本番環境にデプロイできるように、データの変更を一貫してロールアウトできることが望ましい場合があると言います(そしていくつかの手動ステップを実行することを覚えておく必要はありません)。

ただし、シードと移行を分離することには依然として価値があります。これらは2つの関連しますが、明確な懸念であるためです。私たちのチームは、シーダーを呼び出す移行を作成することで妥協しました。これは次のようになります。

public function up()
{
    Artisan::call( 'db:seed', [
        '--class' => 'SomeSeeder',
        '--force' => true ]
    );
}

これにより、移行と同じようにシードを1回実行できます。動作を防止または増強するロジックを実装することもできます。例えば:

public function up()
{
    if ( SomeModel::count() < 10 )
    {
        Artisan::call( 'db:seed', [
            '--class' => 'SomeSeeder',
            '--force' => true ]
        );
    }
}

SomeModelsが10未満の場合、これは明らかに条件付きでシーダーを実行します。これは、呼び出しartisan db:seed時と移行時に実行される標準のシーダーとしてシーダーを含めて、「ダブルアップ」しないようにする場合に役立ちます。ロールバックが期待どおりに機能するように、リバースシーダーを作成することもできます。

public function down()
{
    Artisan::call( 'db:seed', [
        '--class' => 'ReverseSomeSeeder',
        '--force' => true ]
    );
}

2番目のパラメーター--forceは、seederを実稼働環境で実行できるようにするために必要です。


2
これは断然最良の答えです。懸念を分離する保守可能なコード!
Helsont 2016年

18
移行スクリプトからシーダーを呼び出すことの長期的な影響を慎重に検討します。移行スクリプトは日付/時刻でバージョン管理されていますが、シーダーは通常はバージョン管理されていません。開発中、シーダーのニーズは頻繁に変更されるため、バージョン管理されていないシーダーを実行するバージョン管理された移行スクリプトが実行される可能性があり、べき等性が失われます。つまり、同じ移行スクリプトのセットを毎日実行すると、異なる結果が生じる可能性があります。
originalbryan

2
これを投稿して久しぶりに、このテクニックを使って私たちの経験を提供したいと思いました。全体的にそれは私たちにとってはうまくいきました、そして私がもう一度それをしなければならなかったならば、私はそうします。とはいえ、注意すべき1つの問題があります。@originalbryanは正確であり、その結果、新しいDBを起動すると移行が中断する状況に時々遭遇します。移行を実行するとシーダー(およびモデル)がデータベースよりも最新であるためです(シードする可能性があるため)スキーマが完全に更新される前)。その場合は、古い移行を更新して問題に対処します。
darrylkuhn 2017

@darrylkuhn古い移行ファイルを更新することは良い習慣ではないと聞きます-古いファイルを更新する代わりに、新しい移行ファイルを作成する必要があります-これは、設計による移行ファイルの「ワークフロー」です
KamilKiełczewski17年

2
Laravelのすべての言語は、シーダーがテストデータ用であることを意味しているので、設計については留意する必要があると思います。アプリの一部であるデータとテストデータを区別することが重要です。移行に必要なデータを直接含めると、その区別が非常に明確になります。
Brettins

13

LaravelのDatabase Seederを使用する方が、Migrationsを使用するよりも好ましい理由については、次のように説明します。http://laravelbook.com/laravel-database-seeding/

ただし、上記のリンクで説明されている実装が機能していないようで、不完全であるため、公式ドキュメントの指示に従う方がはるかに優れています。 http://laravel.com/docs/migrations#database-seeding


1
私はあなたのエリンに同意します。移行とシードデータを混在させないでください。本番環境ではなく開発環境に一部のデータをシードする可能性が高いためです。
Daniel Vigueras 2014

18
良い点ですが、本番環境にデータが存在しなければならない状況もあります。たとえば、顧客が初めてログインできるように、最初のデフォルトの管理ユーザーが存在する必要があります。事前設定された承認の役割がいくつか存在している必要があり、ビジネスロジックデータもすぐに必要になる場合があります。したがって、必須のデータを移行に追加する必要があると思います(個別の移行を通じてデータレコードもアップ/ダウンできるようにするため)が、開発のためにシードを残すことができます。
JustAMartin 2015

小さなメモ。データベースシードへのリンクは次のとおり
5.3

3

これはあなたが望むことをするはずです。

public function up()
{
    DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}

1

これを行うもう1つのクリーンな方法は、インスタンスを作成し、関係するモデルを永続化するプライベートメソッドを定義することです。

public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('label', 256);
        $table->timestamps();
        $table->softDeletes();
    });

    $this->postCreate('admin', 'user');
}

private function postCreate(string ...$roles)  {
    foreach ($roles as $role) {
        $model = new Role();
        $model->setAttribute('label', $role);
        $model->save();
    }
}

このソリューションでは、タイムスタンプフィールドがEloquentによって生成されます。

編集:シーダーシステムを使用して、データベース構造の生成とデータベースの作成を区別することをお勧めします。


私はこれが好きです...それは私がする必要があるものを正確にサーバーします、移行時にいくつかのユーザーロールをデフォルトで追加します。モデルをインポートするか、直接参照する必要があります$model = new App\UserRoles();が、それ以外は...完璧です!
FAB

1

私はこのDB挿入方法を試しましたが、モデルを使用しないため、モデルにある緩やかな特性を無視しました。そのため、このテーブルのモデルが存在することを前提として、移行後すぐに、モデルを使用してデータを挿入できると考えました。そして私はこれを思いつきました:

public function up() {
        Schema::create('parent_categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
        ParentCategory::create(
            [
                'id' => 1,
                'name' => 'Occasions',
            ],
        );
    }

これは正しく機能し、モデルのスラッガブルトレイトも考慮して、このエントリのスラグを自動的に生成し、タイムスタンプも使用しました。NB。IDを追加する必要はありませんでしたが、この例では、カテゴリに特定のIDが必要でした。Laravel 5.8で動作確認済み


0

すでに列を入力していて、新しい列を追加した場合、または古い列に新しいモック値を入力する場合は、次のようにします。

public function up()
{
    DB::table('foydabars')->update(
        array(
            'status' => '0'
        )
    );
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.