Laravel 4,如何为具有关系的表创建种子数据?
Posted
技术标签:
【中文标题】Laravel 4,如何为具有关系的表创建种子数据?【英文标题】:Laravel 4, how to I create seed data to tables with relationships? 【发布时间】:2013-06-27 17:46:43 【问题描述】:我创建了一个包含两个表“goals”和“partgoals”的数据库。实际用途是制定储蓄目标(金钱)并在此过程中设定里程碑(部分目标)。我希望部分目标显然与特定目标相关联。关系已创建,但在尝试创建种子数据时遇到了麻烦。
我的目标是建立两个这样的目标表(GoalsTableSeeder.php):
<?php
class GoalsTableSeeder extends Seeder
public function run()
DB::table('goals')->delete();
$goals = array(
array(
'max' => 1850000,
'avgsav' => 3500,
'duedate' => date('2015-03-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'max' => 1100000,
'avgsav' => 5000,
'duedate' => date('2013-11-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('goals')->insert( $goals );
我的 partgoals 表是这样的(PartgoalsTableSeeder.php):
<?php
class PartgoalsTableSeeder extends Seeder
public function run()
DB::table('partgoals')->delete();
$partgoals = array(
array(
'id' => 1,
'milestone' => 100000,
'duedate' => date('2014-03-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 1,
'milestone' => 20000,
'duedate' => date('2013-06-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 2,
'milestone' => 400000,
'duedate' => date('2013-09-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
),
array(
'id' => 2,
'milestone' => 200000,
'duedate' => date('2014-10-15'),
'created_at' => new DateTime,
'updated_at' => new DateTime,
)
);
DB::table('partgoals')->insert( $partgoals );
“目标”的迁移表:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGoalsTable extends Migration
/**
* Run the migrations.
*
* @return void
*/
public function up()
Schema::create('goals', function(Blueprint $table)
$table->increments('id');
$table->integer('max');
$table->float('avgsav');
$table->date('duedate');
$table->timestamps();
);
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
Schema::drop('goals');
部分目标的迁移表:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePartgoalsTable extends Migration
/**
* Run the migrations.
*
* @return void
*/
public function up()
Schema::create('partgoals', function(Blueprint $table)
$table->foreign('id')
->references('id')->on('goals')
->onDelete('cascade');
$table->increments('id');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
);
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
Schema::drop('partgoals');
我做错了什么?我是 Laravel(和 Laravel 4)的新手。
【问题讨论】:
您可能会从描述您遇到的麻烦中受益。是否有特定的错误消息/警告?是您的数据不存在/不符合预期吗?等 抱歉,起初我似乎很清楚 =) 我在控制台中遇到了这个问题:[Exception] SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY' (SQL :插入partgoals
(id
,milestone
,duedate
,created_at
,updated_at
)值(?,?,?,?,?),(?,?,?,?,? ), (?, ?, ?, ?, ?), (?, ?, ?, ?, ?)) 以及我要插入的数据。
【参考方案1】:
我发现您的代码存在一些问题:
1) 创建外键的方式
在分配外键约束时,您应该将该列设为unsignedInteger
。在下面的代码中,我将更正您将两列命名为“id”的错误。
Schema::create('partgoals', function(Blueprint $table)
$table->increments('id');
$table->unsignedInteger('goal_id');
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
);
2) 为数据库播种的方式
如果指定外键,则应在表播种器中创建条目时声明该值。
如果要指定 NULL
值,可以通过允许列接受这样的值来完成(默认情况下不接受)。在这种情况下,我们应该添加->nullable()->default(NULL)
Schema::create('partgoals', function(Blueprint $table)
$table->increments('id');
$table->unsignedInteger('goal_id')->nullable()->default(NULL);
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
);
小错误
3)您在播种机中两次传递'id' => 1
【讨论】:
这个文件在 Laravel 文件结构中的什么位置? @AndrewKoperapp/database/migrations
你能举个例子说明“创建条目时声明值”是什么意思吗,我也在尝试为关系数据库做种
只需使用'field' => 'value'
。该部分的重点是:“如果它不可为空,则必须设置外键”【参考方案2】:
在查询构建器中使用 increments
时,它会自动使您的主键自动递增且唯一。除非它是一对一的关系,否则您不能将外键也作为主键。但这只是糟糕的设计。您的架构应如下所示。
Schema::create('partgoals', function(Blueprint $table)
$table->increments('id');
$table->foreign('goal_id')
->references('id')->on('goals')
->onDelete('cascade');
$table->float('milestone');
$table->date('duedate')->nullable();
$table->timestamps();
);
另外,在播种时,如果你在插入时使用insertGetId
,它会返回你刚刚插入的记录的ID。这可以在另一个插入中使用,例如稍后插入另一个表。但是,这必须在同一个脚本中进行。您也许可以将其传回DatabaseSeeder
,然后再传回另一个种子脚本,但我还没有尝试过。
【讨论】:
【参考方案3】:我不熟悉 Laravel,或者您正在尝试做什么,但根据您在 cmets 中添加的错误,您的问题似乎是由于尝试使用相同的主键输入多条记录( 1) 进入您的partgoals
表。
我不确定您是如何设置表的,但您似乎定义了一个带有唯一主键列 ID
的 partgoals
表,您还尝试将其用作引用goals
表的外键。在partgoals
表中创建另一个字段来保存您的外键可能值得。
【讨论】:
【参考方案4】:要播种有关系的表,需要在 ModelFactory.php 文件中定义模型工厂,然后创建播种器类来运行播种器。
例如。模型工厂.php
$factory->define(App\Category::class, function (Faker\Generator $faker)
$name = $faker->name;
return [
'name' => $name,
'visible' => 1
];
);
$factory->define(App\Video::class, function (Faker\Generator $faker)
return [
'title' => $faker->name,
'description' => '',
'status' => 1
];
);
那么seeder类可以如下
<?php
use Illuminate\Database\Seeder;
class CategoriesTableSeeder extends Seeder
/**
* Run the database seeds.
*
* @return void
*/
public function run()
$categories = factory(App\Category::class, 20)->create()->each(function ($u)
for ($i=0; $i<5; $i++)
$u->videos()->save(factory(App\Video::class)->make());
);
您可以参考这篇文章,了解如何为关系为http://deepdivetuts.com/seeding-two-tables-using-laravel-5-3的两个表生成种子
【讨论】:
以上是关于Laravel 4,如何为具有关系的表创建种子数据?的主要内容,如果未能解决你的问题,请参考以下文章
markdown 在Laravel 5.7种子文件中截断具有外键约束的表。
我应该如何为需要引用数据透视表的表配置 Laravel / OctoberCMS 模型?