laravel 需要重置计数器的一对多数据库播种
laravel database seeding with one to many where counter needs to reset
我正在为食谱应用创建 api,但在生成种子数据时遇到了问题。食谱数据库有 4 个 table:用户、食谱、recipe_ingredients 和 recipe_steps。
用户有很多食谱。
配方属于用户。
食谱有许多成分(1 到 n)。
食谱有许多步骤(1 到 n)。
到目前为止,种子生成代码似乎可以为每个食谱随机生成 5 到 10 种成分。在为步骤生成数据时,step_order 会针对每个配方不断增加,但不是我期望的方式。我需要每个食谱的 step_order 从 1 开始。
我 运行 在本地 ubuntu 18.04 桌面上使用内置 php 服务器进行开发。
这是我对 table 迁移的了解:
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);
}
配方工厂:
$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),
];
});
数据库播种器:
// 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());
});
});
我没有收到任何错误消息。
我希望 recipe_steps table 中的 step_order 对于每个食谱从 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...
我在想我需要某种中间体 table。我读过的另一个与此相关的术语是枢轴 table。我唯一熟悉的是中间 table 但我不知道如何在 Laravel 中实现一个,如果那是我需要的话。
如果您需要进一步说明,请告诉我。
我会从 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]));
}
我正在为食谱应用创建 api,但在生成种子数据时遇到了问题。食谱数据库有 4 个 table:用户、食谱、recipe_ingredients 和 recipe_steps。
用户有很多食谱。 配方属于用户。 食谱有许多成分(1 到 n)。 食谱有许多步骤(1 到 n)。
到目前为止,种子生成代码似乎可以为每个食谱随机生成 5 到 10 种成分。在为步骤生成数据时,step_order 会针对每个配方不断增加,但不是我期望的方式。我需要每个食谱的 step_order 从 1 开始。
我 运行 在本地 ubuntu 18.04 桌面上使用内置 php 服务器进行开发。
这是我对 table 迁移的了解:
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);
}
配方工厂:
$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),
];
});
数据库播种器:
// 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());
});
});
我没有收到任何错误消息。
我希望 recipe_steps table 中的 step_order 对于每个食谱从 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...
我在想我需要某种中间体 table。我读过的另一个与此相关的术语是枢轴 table。我唯一熟悉的是中间 table 但我不知道如何在 Laravel 中实现一个,如果那是我需要的话。
如果您需要进一步说明,请告诉我。
我会从 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]));
}