在Laravel迁移文件中填充数据库

Ada*_*son 95 php migration mysql-error-1146 laravel

我只是在学习Laravel,并且有一个工作的迁移文件来创建一个用户表.我试图填充用户记录作为迁移的一部分:

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
            )
        );

    });
}
Run Code Online (Sandbox Code Playgroud)

但是我在运行时遇到以下错误php artisan migrate:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist
Run Code Online (Sandbox Code Playgroud)

这显然是因为Artisan还没有创建表,但所有文档似乎都说有一种方法可以使用Fluent Query来填充数据作为迁移的一部分.

谁知道怎么样?谢谢!

Ben*_*nRH 193

不要将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
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

  • 以及如何插入多个数据? (4认同)
  • @ SuperMario'sYoshi我认为类似这样的东西:DB :: table('users')-> insert([['email'=>'taylor@example.com','votes'=> 0],['email' =>'dayle@example.com','votes'=> 0]]);` (2认同)

dar*_*uhn 76

我知道这是一个老帖子,但是因为它出现在谷歌搜索中,我想我会在这里分享一些知识.@ erin-geyer指出混合迁移和播种器可能会让人感到头疼,@ justamartin反驳说,有时您希望/需要将数据作为部署的一部分进行填充.

我更进一步说,有时希望能够一致地推出数据更改,以便您可以部署到分段,看到一切都很好,然后在相同结果的信心下部署到生产(而不必记住运行一些手动步骤).

然而,将种子和迁移分开仍然是有价值的,因为这是两个相关但不同的问题.我们的团队通过创建称为播种者的迁移而妥协.这看起来像:

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

这允许您像迁移一样执行一次种子.您还可以实现阻止或增强行为的逻辑.例如:

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

如果少于10个SomeModel,这显然会有条件地执行你的播种机.如果您希望将播种机作为标准播种机包含在您调用时artisan db:seed以及迁移时执行的标准播种机,这样您就不会"加倍".您还可以创建反向播种器,以便回滚按预期工作,例如

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

--force需要第二个参数才能使播种机在生产环境中运行.

  • 我会小心地考虑从迁移脚本调用播种器的长期影响.迁移脚本是日期/时间版本,而播种器通常不是.在开发期间,播种机需求经常发生变化,导致版本化迁移脚本运行非版本化播种机的可能性 - 打破幂等性.换句话说,每天运行同一组迁移脚本可能会产生不同的结果. (17认同)
  • 到目前为止,这是最好的答案。可维护的代码将关注点分开! (2认同)
  • 我发布这篇文章已经有一段时间了,我想提供我们使用这种技术的经验。总的来说,它对我们来说效果很好,如果我不得不再做一次,我会的。也就是说,有一个问题需要注意。@originalbryan 是完全正确的,结果是我们偶尔会遇到在启动新数据库时迁移中断的情况,因为随着迁移运行,播种器(和模型)比数据库更新(因为我们可能会播种在架构完全更新之前)。发生这种情况时,我们会更新旧迁移以解决该问题。 (2认同)
  • @darrylkuhn 是的,你的提议打破了这条规则。如果我们不在迁移文件内调用播种器,而是将“INSERT-s”直接放入迁移文件中,那么我们就保存了数据一致性,而无需更改旧的迁移文件。事实上,我显然没有看到将 INSERT 放入迁移文件中的问题 - 例如,我的系统有 30 个表,并且想要添加需要带有一些初始数据的新表的新功能 - 所以我将初始数据放入迁移文件中(在单独的方法中) - 没问题:P (2认同)
  • Laravel的所有语言都暗示着种子是用于测试数据的,因此我认为设计时应牢记这一点。区分应用程序中的数据与测试数据之间的区别很重要,并且在迁移中直接包含所需的数据可以使这种区别非常明显。 (2认同)

Eri*_*yer 11

这里有一个非常好的解释,为什么使用Laravel的数据库播种器比使用迁移更可取:http://laravelbook.com/laravel-database-seeding/

虽然遵循官方文档上的说明是一个更好的主意,因为上述链接中描述的实现似乎不起作用且不完整. http://laravel.com/docs/migrations#database-seeding

  • 好的,但有些情况下生产环境中必须存在一些数据.例如,第一个默认管理员用户必须存在,以便客户可以首次登录,必须存在一些预设授权角色,也可能需要立即生成某些业务逻辑数据.因此,我认为应该将强制数据添加到迁移中(这样您就可以通过单独的迁移来增加/减少数据记录),但种子可以留给开发. (17认同)
  • 我同意你的观点,艾琳。不要将迁移与种子数据混合在一起,因为您很可能希望在开发环境中而不是在生产环境中种子一些数据。 (4认同)
  • 请包含链接文章的相关部分。不鼓励[仅链接答案](https://meta.stackoverflow.com/tags/link-only-answers/info)。你的第一个链接已经失效了,我不得不从 archive.org 将它恢复! (2认同)

Mar*_*bae 10

如果您使用 Laravel 8 并且想要使用多个记录进行初始化,您可以通过这两种方式中的任何一种来完成。

1. 不推荐的方式

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

        DB::table('categories')->insert(
            array(
                [
                    'name' => 'Category1',
                ],
                [
                    'name' => 'Category2',
                ],
                [
                    'name' => 'Category3',
                ],
            )
        );
    }
Run Code Online (Sandbox Code Playgroud)

上面的方法很好,但会将created_atupdated_at列留空。

2. 推荐方式

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


        $data =  array(
            [
                'name' => 'Category1',
            ],
            [
                'name' => 'Category2',
            ],
            [
                'name' => 'Category3',
            ],
        );
        foreach ($data as $datum){
            $category = new Category(); //The Category is the model for your migration
            $category->name =$datum['name'];
            $category->save();
        }

    }
Run Code Online (Sandbox Code Playgroud)

  • 它不会工作,因为模型当时不存在......永远不要在迁移中使用模型,因为你最终可能会引用在某个时候被删除的模型......这些天我正在处理类似的问题其他开发人员所犯的错误。 (2认同)

str*_*s28 5

这应该做你想做的。

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