Сводная таблица Factory Seed в Laravel с отношениями «многие ко многим» - PullRequest
0 голосов
/ 09 сентября 2018

Я совершенно новичок в фабриках и семенах, и до сих пор я вручную добавлял данные в каждый проект в Sequel Pro или Workbench.

Я довольно новичок в Laravel в целом, но я думаю, что я правильно настроил модели.

У меня есть рецепт, который может содержать несколько ингредиентов, а ингредиенты могут принадлежать нескольким рецептам.

В стержне между ними есть столбец количества и единицы (последний обнуляется).

Recipe.php

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

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

}

Ingredient.php

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

IngredientFactory.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'),
    ];
});

RecipeFactory.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'),
    ];
});

IngredientTableSeeder

public function run()
{
    factory(App\Ingredient::class, 100)->create();
}

RecipeTableSeeder

public function run()
{
    factory(App\Recipe::class, 30)->create();
}

Это все работает нормально, но я пытаюсь понять, как я могу генерировать данные для сводной таблицы.

Я чувствую, что это должно быть примерно так:

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),        
    ];
});

Но я бы не был уверен, что поставить как ? для model::class?

Я мог бы быть совершенно не в себе, но логика кажется правильной.

Пожалуйста, дайте мне знать в комментариях, если потребуется дополнительная информация.

1 Ответ

0 голосов
/ 09 сентября 2018

Вообще говоря, вы определяете таблицу сопоставления, которая обеспечивает связь между рецептом и его ингредиентами. С очень упрощенной точки зрения, у вас не будет модели для этой ссылки во многих отношениях многих, потому что отношения не имеют никакого значения, кроме связи. В этом случае вы можете построить Сеялку рецептов следующим образом:

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]
        );
    });
}

Это сгенерирует и рецепты, и ингредиенты независимо, и тогда вы просто соотносите их стандартным образом. Вы также можете сгенерировать их каждый в другой сеялке, и у вас есть третий, чтобы сделать соединения.

В вашем конкретном случае вы присоединяетесь к рецептам и ингредиентам. Соответствующие отношения будут иметь свои собственные атрибуты, например, сколько граммов ингредиента вам нужно для рецепта. В этом случае может оказаться полезной модель соединения. Взгляните на https://laravel.com/docs/5.7/eloquent-relationships#many-to-many в разделе Определение пользовательских промежуточных таблиц моделей .

...