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

时间:2012-10-04 21:18:36

标签: php laravel migration mysql-error-1146

我只是在学习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
            )
        );

    });
}

但是在运行php artisan migrate时出现以下错误:

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

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

任何人都知道怎么做?谢谢!

9 个答案:

答案 0 :(得分:171)

不要将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
        )
    );
}

答案 1 :(得分:68)

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

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

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

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

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

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

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

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

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

答案 2 :(得分:10)

以下是一个非常好的解释,说明为什么使用Laravel的数据播种机比使用迁移更受欢迎:http://laravelbook.com/laravel-database-seeding/

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

答案 3 :(得分:2)

这应该做你想要的。

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

答案 4 :(得分:2)

如果您使用的是 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',
                ],
            )
        );
    }

上述方法很好,但会将 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();
        }

    }

答案 5 :(得分:0)

另一种干净的方法是定义一个私有方法来创建实例并持久保存相关模型。

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生成。

编辑: 最好使用种子系统区分数据库结构生成和数据库填充。

答案 6 :(得分:0)

我尝试了这种数据库插入方法,但是由于它不使用模型,因此它忽略了我在模型上具有的易碎特性。因此,考虑到该表的模型存在,一旦迁移,我就认为该模型可用于插入数据。我想出了这个:

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',
            ],
        );
    }

这可以正常工作,并且还考虑了我模型上的可滞性特征,从而自动为此条目生成一个滞后,并且也使用了时间戳。 注意无需添加ID,但是在此示例中,我想为我的类别指定特定的ID。 测试过Laravel 5.8上的工作

答案 7 :(得分:0)

如果您已经填充了列并添加了新列,或者想用新的模拟值填充旧列,请执行以下操作:

public function up()
{
    DB::table('foydabars')->update(
        array(
            'status' => '0'
        )
    );
}

答案 8 :(得分:-11)

尝试:(未经测试)

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

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

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

    });
}