Laravel多态数据库播种机工厂

时间:2018-03-10 04:47:26

标签: laravel-5 polymorphic-associations laravel-seeding

如何为以下配置创建数据库浏览器工厂?

用户

// create_users_table.php
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    ...
}

// User.php
public function notes()
{
    return $this->morphMany('App\Note', 'noteable');
}

复合

// create_complex_table.php
Schema::create('complex', function (Blueprint $table) {
    $table->increments('id');
    ...
}

// Complex.php
public function notes()
{
    return $this->morphMany('App\Note', 'noteable');
}

备注

// create_notes_table.php
Schema::create('notes', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('noteable_id');
    $table->string('noteable_type');
    ...
}

// Note.php
public function noteable()
{
    return $this->morphTo();
}

我正在努力寻找最有力的方法来确保我不仅仅填写可能不存在的随机id

5 个答案:

答案 0 :(得分:2)

我改进了HyperionX的答案,并从中删除了静态元素。

$factory->define(App\Note::class, function (Faker $faker) {
    $noteable = [
        App\User::class,
        App\Complex::class,
    ]; // Add new noteables here as we make them
    $noteableType = $faker->randomElement($noteables);
    $noteable = factory($noteableType)->create();

    return [
        'noteable_type' => $noteableType,
        'noteable_id' => $noteable->id,
        ...
    ];
});

基本上,我们随机选择一个值得注意的类,然后调用它自己的工厂来获得一个值得注意的实例,从而摆脱了OP答案的静态性。

答案 1 :(得分:1)

您也可以在没有这样的临时变量的情况下执行此操作:

$factory->define(App\Note::class, function (Faker $faker) {
    return [
        'noteable_type' => $faker->randomElement([
            App\User::class,
            App\Complex::class,
        ]),
        'noteable_id' => function (array $note) {
            return factory($note['noteable_type']);
        },
        ...
    ];
})

答案 2 :(得分:1)

如果使用的是变体贴图,则给定的解决方案将不起作用,因为类型将与类名不同。

这将与变形贴图结合使用。

$factory->define(App\Note::class, function (Faker $faker) {
    $noteable = $faker->randomElement([
        App\User::class,
        App\Complex::class,
    ]);

    return [
        'noteable_id' => factory($noteable),
        'noteable_type' => array_search($noteable, Relation::$morphMap),
        ...
    ];
});

有关变形图的更多信息,请参见:https://laravel.com/docs/7.x/eloquent-relationships#custom-polymorphic-types

答案 3 :(得分:0)

虽然比我想要的更静一些,但这是我的解决方案:

我为每个类创建了20个模型,这样我就可以确保创建的Notes不会尝试链接到可能不存在的内容,留下悬空的Note对象。

// NotesFactory.php
$factory->define(App\Note::class, function (Faker $faker) {
    $noteable = [
        App\User::class,
        App\Complex::class,
    ];

    return [
        'noteable_id' => $faker->numberBetween(0,20),
        'noteable_type' => $faker->randomElement($noteable),
        ...
    ];
});

答案 4 :(得分:0)

如果您已经通过不同的工厂创建了具体Notables的实例,则可能不想再创建它的新实例。在这种情况下,您可以扩展Barracuda's solution

$factory->define(App\Note::class, function (Faker $faker) {
    $noteable = [
        User::class,
        Complex::class,
    ];

    $noteableType = $faker->randomElement($noteable);
    if ($noteableType === User::class) {
        $noteableId = User::all()->random()->id;
    } else {
        $noteableId = Complex::all()->random()->id;
    }

    return [
        'noteable_type' => $noteableType,
        'noteable_id' => $noteableId,
        ...
    ];
});

我意识到这将需要一些额外的开销来维护if / else分支,但是您将不会遇到使用不存在的ID的问题。

也许还有一种更优雅,更通用的方法来基于Model::all()获取Model::class,但是我对此并不了解。