在 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.example`,
'verified' => true
)
);


});
}

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

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

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

有人知道怎么做吗?

149164 次浏览

不要将 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.example',
'verified' => true
)
);
}

这应该是你想要的。

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

这里有一个很好的解释,为什么使用 Laravel 的数据库播种器优于使用迁移: https://web.archive.org/web/20171018135835/http://laravelbook.com/laravel-database-seeding/

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

我知道这是一个老的帖子,但是因为它出现在谷歌搜索,我想我会在这里分享一些知识。@ erin-geyer 指出,混合迁移和播种器可能会带来麻烦,而@just amartin 则反驳说,有时候你希望/需要将数据填充到部署中。

我想更进一步说,有时候我们希望能够一致地推出数据更改,这样您就可以例如部署到临时阶段,看到一切正常,然后部署到生产环境,并对相同的结果抱有信心(而不必记得运行某些手动步骤)。

然而,分离出种子和迁移仍然有价值,因为这是两个相互关联但又截然不同的问题。我们的团队已经妥协了,创造了称为播种机的迁移。这看起来像:

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个 Some 模型,这显然会有条件地执行您的播种器。这是有用的,如果你想包括作为一个标准播种机,执行时,您调用 artisan db:seed以及当您迁移,以便您不“双重”。您还可以创建一个反向播种器,以便回滚按预期工作,例如。

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

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

另一种干净的方法是定义一个私有方法,它创建实例并持久化相关的 Model。

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 将生成时间戳字段。

编辑: 利用播种机系统可以更好地区分数据库结构生成和数据库填充。

我尝试了这种 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',
],
);
}

这种方法工作正常,而且还考虑到了 Model 上的可拖动特性,可以为这个条目自动生成一个蛞蝓,并且还使用了时间戳。 注意,添加 ID 是没有必要的,但是,在这个示例中,我需要为我的类别添加特定的 ID。 在 Laravel 5.8上进行测试

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

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

如果您正在使用 Laravel8,并且希望使用 多个记录进行初始化,则可以使用以下两种方法中的任何一种。

不被推荐的方法

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

上面的方法很好,但是将留下空白的 创建 _ at更新 _ 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();
}


}

通过编辑 Martin Mbae 的回答中的第一个选项,如果您希望得到与第二个选项相同的结果,但不使用模型,那么您可以这样做:

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


$sampleData = ['sample1', 'sample2', 'sample3'];
$data = [];


foreach ($sampleData as $sample) {
$data[] = [
'table_name' => $sample,
'created_at' => now(),
'updated_at' => now()
];
}
    

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