Child table seeding for an incremental column in laravel

65 Views Asked by At

stores table (id, name)

store_opening_hours table (id, store_id, day_of_week, opens_at, closes_at)

StoreFactory.php file:

class StoreFactory extends Factory
{
    public function definition(): array
    {
        return [
            'name' => fake()->company
        ];
    }
}

StoreOpeningHourFactory.php file:

class StoreOpeningHourFactory extends Factory
{
    public function definition(): array
    {
        return [
            'store_id' => Store::factory(),
            'day_of_week' => // What to put here?,
            'opens_at' => fake()->time('H:i'),
            'closes_at' => fake()->time('H:i'),
        ];
    }
}

StoreSeeder.php file:

class StoreSeeder extends Seeder
{
    public function run(): void
    {
        Store::factory()
            ->has(StoreOpeningHour::factory()->count(7))
            ->create(10);
    }
}

The day_of_week will always be incrementing from [0-6] for each store. How to do that inside StoreOpeningHourFactory.php file?

2

There are 2 best solutions below

1
Efros Ionelu On

One idea is to use

$this->faker->unique()->numberBetween(0, 6)

But you can add only 7 rows, will also be awesome to store week_of_the_year so you have unique on 2 columns

You also have some notes there How to get unique values from faker?

Another implementation, you can use afterMaking callback, add an array of possible values and delete a random value from it, when array is empty get the default array

 public function configure()
    {
        return $this->afterMaking(function (StoreOpeningHour $storeOpeningHour) {
             $this->definition['day_of_week'] = #random_value_from_one_to_six#

        });
    }
0
Mohammad Salah On

For now, I am solving it like this:

class StoreOpeningHourFactory extends Factory
{
    private static int $dayOfWeek = 0;

    public function definition(): array
    {
        return [
            'store_id' => Store::factory(),
            'day_of_week' => static::$dayOfWeek++ % 7,
            'opens_at' => fake()->time('H:i'),
            'closes_at' => fake()->time('H:i'),
        ];
    }
}