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 :插入partgoalsidmilestoneduedatecreated_atupdated_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 值,可以通过允许列接受这样的值来完成(默认情况下不接受)。在这种情况下,我们应该添加-&gt;nullable()-&gt;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' =&gt; 1

【讨论】:

这个文件在 Laravel 文件结构中的什么位置? @AndrewKoper app/database/migrations 你能举个例子说明“创建条目时声明值”是什么意思吗,我也在尝试为关系数据库做种 只需使用'field' =&gt; '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 表。

我不确定您是如何设置表的,但您似乎定义了一个带有唯一主键列 IDpartgoals 表,您还尝试将其用作引用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 模型?

Laravel 4:处理种子中的关系

如何为超过 3000 万行和 250 列的表优化 Oracle 创建表功能

在 Laravel 中填充具有多对多关系的表

Java:如何为多个文件或目录创建种子文件?