заполнение базы данных laravel от одного ко многим, где необходимо сбросить счетчик - PullRequest
0 голосов
/ 21 сентября 2019

Я создаю API для приложения рецептов, и у меня возникают проблемы с генерацией начальных данных.База данных рецептов имеет 4 таблицы: пользователи, рецепты, recipe_ingredients и recipe_steps.

У пользователя есть много рецептов.Рецепт принадлежит Пользователю.Рецепт имеет много ингредиентов (от 1 до n).Рецепт имеет много шагов (от 1 до n).

До сих пор код создания семени, кажется, работал до и включал в себя создание от 5 до 10 ингредиентов случайным образом для каждого рецепта.При генерации данных для шагов, step_order продолжает увеличиваться для каждого рецепта, но не так, как я ожидаю.Мне нужно, чтобы step_order начинался с 1 для каждого рецепта.

Я выполняю это на локальном рабочем столе Ubuntu 18.04 в разработке с использованием встроенного php-сервера.

Вот что у меня есть для миграции таблиц:

create_recipes_table:

if (!Schema::hasTable('recipes')) {
   Schema::create('recipes', static function (Blueprint $table) {
     $table->bigIncrements('id');
     $table->unsignedBigInteger('user_id')->nullable();
     $table->foreign('user_id')->references('id')->on('users');
     $table->string('title', 256);
     $table->longText('description');
     $table->timestamps();
   });
}

create_recipe_ingredients_table:

if (!Schema::hasTable('recipe_ingredients')) {
   Schema::create('recipe_ingredients', static function (Blueprint $table) {
     $table->unsignedBigInteger('recipe_id');
     $table->string('name', 100);
     $table->string('quantity', '15');
     $table->timestamps();
     $table->foreign('recipe_id')->references('id')->on('recipes')->onDelete('cascade');
    });
}

create_recipe_steps_table:

if (!Schema::hasTable('recipe_steps')) {
   Schema::create('recipe_steps', static function (Blueprint $table){
      $table->unsignedBigInteger('recipe_id');
      $table->unsignedInteger('step_order');
      $table->text('description');
      $table->timestamps();
      $table->foreign('recipe_id')->references('id')->on('recipes')->onDelete('cascade');
   });
}

Модель рецепта:

public function User(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        /** @var Recipe $this */
        return $this->belongsTo(User::class);
    }

    /**
     * @return HasMany
     */
    public function ingredients(): HasMany
    {
        return $this->hasMany(Ingredient::class);
    }

    public function steps(): HasMany
    {
        return $this->hasMany(Ingredient::class);
    }

Модель ингредиента:

public function Recipe(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
    /** @var Ingredient $this */
    return $this->belongsTo(Recipe::class);
}

Модель шага:

public function Recipe(): BelongsTo
{
     /** @var Ingredient $this */
     return $this->belongsTo(Recipe::class);
}

RecipeFactory:

$factory->define(Recipe::class, static function (Faker $faker) {
    return [
        'user_id' => factory(User::class)->create()->id,
        'title' => rtrim($faker->sentence(random_int(5, 10)), '.'),
        'description' => $faker->paragraphs(random_int(3, 7), true),
    ];
});

RecipeIngredientsFactory:

$factory->define(Ingredient::class, static function (Faker $faker) {
    $quantityTypeAmount = $faker->randomFloat(2, 0, 10);
    $quantityTypeString = $faker->randomElements(
        ['tsp.', 'tbsp.', 'fl oz.', 'gill.', 'cup.', 'pt.', 'qt.', 'gal.', 'ml.', 'L', 'dl',]
    );
    return [
        'name' => $faker->words(random_int(3, 7), true),
        'quantity' => (string)$quantityTypeAmount . ' ' . $quantityTypeString[0]
    ];
});

RecipeStepsFactory:

$factory->define(Step::class, static function (Faker $faker) {
    static $step_order = 1;
    return [
        'step_order' => $step_order++,
        'description' => $faker->sentences(random_int(1, 4), true),
    ];
});

DatabaseSeeder:

// Create 5 users.
factory(User::class, 5)->create()->each(static function (User $user) {
    // Create 5 - 10 recipes for each user.
    factory(Recipe::class, 5)->create(['user_id'=>$user->id])->each(static function (Recipe $recipe) {

        // For each recipe, create 5 - 10 ingredients randomly.
        $recipe->ingredients()->saveMany(factory(Ingredient::class, random_int(3,7))->make());

        // For each recipe, create 1 - 5 steps for each recipe
        $recipe->steps()->saveMany(factory(Step::class,random_int(1,5))->make());

    });
});

Я не получаюлюбые сообщения об ошибках.

Я ожидаю, что step_order в таблице recipe_steps будет увеличиваться с 1 до n для каждого рецепта.Однако в настоящее время step_order продолжает увеличиваться для каждого рецепта.

Например, в настоящее время я получаю:

recipe_id - step_order - description 
    1            1         -------
    1            2         -------
/\/\/\/\/\/\/\/\/\/\/\/\/\/
    1            10        -------
    2            11        -------
    2            12        -------
etc...  

Что я ожидаю:

recipe_id - step_order - description 
    1            1         -------
    1            2         -------
/\/\/\/\/\/\/\/\/\/\/\/\/\/
    1            10        -------
    2            1         -------
    2            2         -------
    2            3         -------
    3            1         -------
    3            2         -------   
etc...

Я думаю, мне нужна какая-то промежуточная таблица.Другой термин, который я прочитал, связанный с этим, является сводной таблицей.Единственная вещь, с которой я знаком, это промежуточная таблица, но я не знаю, как реализовать ее в Laravel, если это то, что мне нужно.

Пожалуйста, дайте мне знать, если вам нужны дополнительные разъяснения.

1 Ответ

1 голос
/ 22 сентября 2019

Я бы удалил вторую строку из RecipeStepsFactory и присвоил бы значение по умолчанию 'step_order' 1

$factory->define(Step::class, static function (Faker $faker) {
    return [
        'step_order' => 1, // default value of 1
        'description' => $faker->sentences(random_int(1, 4), true),
    ];
});

, затем в файле DatabaseSeeder я бы запустил сеялку рецептов следующим образом

$steps = random_int(1,5);

// For each recipe, create 1 - 5 steps for each recipe
for ($i = 1; $i <= $steps; $i++) {
   $recipe->steps()->save(factory(Step::class)->make(['step_order' => $i]));
}

...