I have a User model and a Car model, and a User can have many Cars, and the cars()
relationship should return the user’s cars from the most recently created. Here’s the test I’ve written for this relationship:
public function test_user_has_many_cars_relation_returns_cars_from_the_most_recent() {
$user = User::factory()->create();
$lessRecentCar = Car::factory()->for( $user )->create();
sleep(1);
$mostRecentCar = Car::factory()->for( $user )->create();
$hasManyRelation = $user->cars();
$this->assertHasManyRelation( $hasManyRelation, Car::class, 2 );
$this->assertIsSameModel( $mostRecentCar, $hasManyRelation->first() );
}
This works, however I had to use sleep(1)
to create two cars with a different created_at
value, because unfortunately using Car::factory()->for( $user )->count(10)->create()
(which is a lot nicer) assigns the same value for created_at
to all models.
Is there a better workaround than using sleep(1)
? Hopefully something that doesn’t imply manually assigning a different created_at
value for each model one wants to create?
2
Answers
make sure to enable mass assignment for your Car model first
use
faker
to overridecreated_at
increate()
method:Edit: to get most recent car:
Yes, there is a better workaround than using
sleep(1)
or manually assigning differentcreated_at
values. You can override thecreated_at
value in the factory’s definition using theafterMaking
andafterCreating
callbacks. Here’s an example:In this example, we’re using the
afterMaking
callback to override thecreated_at
value for each Car model that is made by the factory. TheCarbon::now()->subSeconds(rand(0, 3600))
expression sets thecreated_at
value to a random time within the past hour.Note that we’re using the
rand
function to generate a random number of seconds between 0 and 3600, which is equivalent to 1 hour. This ensures that each Car model will have a differentcreated_at
value and avoids the need for thesleep
function.With this approach, you can create multiple Car models for a User using the
Car::factory()->for($user)->count(10)->create()
method and each Car model will have a uniquecreated_at
value.