So, as an exercise in ORM modeling with laravel, I'm trying to implement this model:
It's a bit tricky for me to write the factories and seeders for the Restaurant - OpeningHours relationship.
How do I make a factory for opening hours that increments the "Day" attribute for each OpeningHour belonging to One restaurant?
By that, I mean there must be 7 OpeningHours for each restaurant, and each should have a "Day" attribute from 1 to 7.
Any Ideas?
here's the code for the OpeningHours Factory:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\OpeningHours>
*/
class OpeningHoursFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
"day" => fake()->numberBetween(0,6),
"from_hour" => 0,
"from_minute" => 0,
"to_hour" => 23,
"to_minute" => 59,
];
}
}
Here's the code for the Restaurant Factory
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Restaurant>
*/
class RestaurantFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->company(),
"short_description" => fake()->text(127),
"description" => fake()->text(254),
"image" => fake()->image(),
"is_active" => fake()->boolean()
];
}
}
And here's the Restaurant Seeder
<?php
namespace Database\Seeders;
use App\Models\OpeningHours;
use App\Models\Restaurant;
use Database\Factories\RestaurantFactory;
use Illuminate\Database\Seeder;
class RestaurantSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Restaurant::factory()->has(OpeningHours::factory()->count(7) )->count(10)->create();
}
}
I will try to write a seeder for you, it may not exactly be what you want, but it is based on what I understood.
Have in mind that seeders allows you to do anything you want, you can even run code that has nothing to do with factories. As the name implies, seeder
is for seeding data (usually known or completely random from factories) into your database, so here you have the choice of full control (what I am going to do) versus complete randomness.
I will use Laravel 12.x:
<?php
namespace Database\Seeders;
use App\Models\OpeningHours;
use App\Models\Restaurant;
use Database\Factories\RestaurantFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Database\Seeder;
class RestaurantSeeder extends Seeder
{
public function run(): void
{
Restaurant::factory()
->count(10)
->create()
->each(function (Restaurant $restaurant) {
/** @var Collection<OpeningHours> $hours */
$hours = OpeningHours::factory()
->count(7)
->sequence(
fn (Sequence $sequence) => ['day' => $sequence->index + 1]
)
->create();
$restaurant->openingHours()->saveMany($hours);
});
}
}
I do not know the relationships you have created (it should be HasMany
for Restaurant
to OpeningHours
), then you can use saveMany
for openingHours
relationship.
This is what is happening:
Restaurant
factory, creating 10 restaurants.Collection
, we can iterate each model, and we do something with each one (associate hours).Restaurant
model, we create 7 new OpeningHours
(the name of the model should be OpeningHour
), and each time one is created, we set the day to be the current index (starts from 0
) + 1, so we go from 1
to 7
.saveMany
using the relationship.