Laravel 中具有多对多关系的工厂种子数据透视表

n8u*_*udd 2 php laravel laravel-seeding

我对工厂和种子完全陌生,直到现在我一直在向 Sequel Pro 或 Workbench 中的每个项目手动添加数据。

总的来说,我对 Laravel 相当陌生,但我认为我已经正确设置了模型。

我有一个可以包含多种成分的食谱,并且这些成分可以属于多个食谱。

两者之间的枢轴有一个数量和单位列(后者可以为空)。

食谱.php

class Recipe extends Model
{
    public function user(){
    return $this->belongsTo('App\User');
    }

    public function ingredients(){
    return $this->belongsToMany('App\Ingredient');
    }

}
Run Code Online (Sandbox Code Playgroud)

成分.php

class Ingredient extends Model
{
    public function recipes(){
        return $this->belongsToMany('App\Recipe');
    }
}
Run Code Online (Sandbox Code Playgroud)

原料工厂.php

$factory->define(App\Ingredient::class, function (Faker $faker) {
    return [
        'name'       => $faker->word,
        'created_at'  => Carbon::now()->format('Y-m-d H:i:s'),
        'updated_at'  => Carbon::now()->format('Y-m-d H:i:s'),
    ];
});
Run Code Online (Sandbox Code Playgroud)

配方工厂.php

$factory->define(App\Recipe::class, function (Faker $faker) {
    $userIds = User::all()->pluck('id')->toArray();

    return [
        'title'       => $faker->text(30),
        'description' => $faker->text(200),
        'user_id'     => $faker->randomElement($userIds),
        'created_at'  => Carbon::now()->format('Y-m-d H:i:s'),
        'updated_at'  => Carbon::now()->format('Y-m-d H:i:s'),
    ];
});
Run Code Online (Sandbox Code Playgroud)

配料表播种机

public function run()
{
    factory(App\Ingredient::class, 100)->create();
}
Run Code Online (Sandbox Code Playgroud)

配方表播种机

public function run()
{
    factory(App\Recipe::class, 30)->create();
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但我正在努力研究如何为数据透视表生成数据。

我觉得它应该是这样的:

RecipeIngredientsFactory.php

$factory->define(?::class, function (Faker $faker) {
    $recipeIds = Recipe::all()->pluck('id')->toArray();
    $ingredientIds = Ingredient::all()->pluck('id')->toArray();

    return [
        'recipe_id'     => $faker->randomElement($recipeIds),
        'ingredient_id' => $faker->randomElement($ingredientIds),        
    ];
});
Run Code Online (Sandbox Code Playgroud)

但是我不能确定什么作为了?model::class

我可能完全偏离基础,但逻辑似乎是正确的。

如果需要更多信息,请在评论中告诉我。

Jas*_*son 6

一般而言,您正在定义提供配方与其成分之间链接的映射表。从一个非常简单的角度来看,在很多多对多关系中,您不会有该链接的模型,因为该关系除了链接之外没有任何意义。在这种情况下,您可以像这样构建一个 Recipe Seeder:

public function run()
{ 
    $recipes = factory(App\Recipe::class, 30)->create();
    $ingredients = factory(App\Ingredient::class, 20)->create();
    $recipes->each(function (App\Recipe $r) use ($ingredients) {
        $r->ingredients()->attach(
            $ingredients->random(rand(5, 10))->pluck('id')->toArray(),
            ['grams' => 5]
        );
    });
}
Run Code Online (Sandbox Code Playgroud)

这将独立生成食谱和成分,然后您只是以标准方式将它们关联起来。您还可以在不同的播种机中分别生成它们,并让第三个进行连接。

在您的特定情况下,您正在加入食谱和配料。对应关系将有自己的属性,例如配方需要多少克成分。在这种情况下,您可能会发现连接模型很有用。在定义自定义中间表模型部分下查看https://laravel.com/docs/5.7/eloquent-relationships#many-to-many