我刚刚学习 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 来填充数据作为迁移的一部分。
有谁知道怎么做?
不要将 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
)
);
}
我知道这是一篇旧帖子,但由于它出现在谷歌搜索中,我想我会在这里分享一些知识。 @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 ]
);
}
}
如果 SomeModel 少于 10 个,这显然会有条件地执行您的播种机。如果您想将播种器作为标准播种器包含在您调用 artisan db:seed
以及迁移时执行的标准播种器中,这样您就不会“加倍”,这很有用。您还可以创建一个反向播种器,以便回滚按预期工作,例如
public function down()
{
Artisan::call( 'db:seed', [
'--class' => 'ReverseSomeSeeder',
'--force' => true ]
);
}
需要第二个参数 --force
才能使播种机在生产环境中运行。
这里很好地解释了为什么使用 Laravel 的 Database Seeder 比使用 Migrations 更可取:https://web.archive.org/web/20171018135835/http://laravelbook.com/laravel-database-seeding/
虽然按照官方文档上的说明是一个更好的主意,因为上面链接中描述的实现似乎不起作用并且不完整。 http://laravel.com/docs/migrations#database-seeding
如果你使用 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_at 和 updated_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();
}
}
这应该做你想要的。
public function up()
{
DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}
另一种干净的方法是定义一个私有方法来创建实例并持久化相关模型。
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();
,但除此之外......完美!
我尝试了这种 DB 插入方法,但由于它不使用模型,因此它忽略了我在模型上具有的 sluggable 特征。因此,鉴于此表的模型存在,一旦它迁移,我认为该模型将可用于插入数据。我想出了这个:
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',
],
);
}
这可以正常工作,并且还考虑了我的模型上的 sluggable 特征来自动为该条目生成一个 slug,并且也使用时间戳。注意。添加 ID 不是必需的,但是,在此示例中,我希望为我的类别提供特定的 ID。测试在 Laravel 5.8 上工作
如果您已经填写了列并添加了新列,或者您想用新的模拟值填写旧列,请执行以下操作:
public function up()
{
DB::table('foydabars')->update(
array(
'status' => '0'
)
);
}
通过从 Martin Mbae's answer 编辑第一个选项,如果您想要与第二个选项相同的结果但不使用模型,您可以这样做:
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);
}
DB::table('users')->insert([ ['email' => 'taylor@example.com', 'votes' => 0], ['email' => 'dayle@example.com', 'votes' => 0] ]);