splitbrain's avatar

Factory faker reuses values?

I have the simple Factory below. The problem is that my tax field always gets filled with the same number as the deposit field. This of course results in much too high tax rates.

It seems like faker is caching results between method calls? That seems un-intuitive and I wonder how to disable that. Any hints?

class PropertyFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'name' => fake()->domainWord(),
            'owner_id' => Owner::inRandomOrder()->first()->id,
            'deposit' => fake()->randomFloat(2, 0, 300),
            'tax' => fake()->randomFloat(2, 0, 30),
            'color' => fake()->hexColor(),
        ];
    }
}
0 likes
7 replies
vincent15000's avatar

It's amazing that you get the same value given that for the deposit, you ask for a value between 0 and 300, whereas for the tax between 0 and 30.

JussiMannisto's avatar

There must be something else going on. Can you show how you determined that the values are identical?

1 like
splitbrain's avatar

Can you show how you determined that the values are identical?

🤦‍♂️ I was about to write a long post on how none of the suggestions here work, when I actually looked into the database and the values were different! It was a stupid copy'n'paste error in my template and I output the same column twice. I could have sworn to have checked that.

Thanks for all the suggestions and sorry for wasting everyone's time.

3 likes
tisuchi's avatar

@splitbrain Can you try with unique()?

e.g.

 'deposit' => fake()->unique()->randomFloat(2, 0, 300),
1 like
MouteeSabouni's avatar

@tisuchi Using unique() here makes the value unique in the column, not in the row, or am I wrong? Even if he used it, he could still get the same value for deposit and tax, only the deposit value won't be repeated in the column, correct?

1 like
tisuchi's avatar

@Moutee If I understand you correctly the unique() method in Laravel's factories ensures that the generated value for a specific field is unique across all records for that factory instance.

Unfortunately, it is not column-specific but applies across all generated records.

1 like
martinbean's avatar

@splitbrain If you create many models in one go (i.e. using Property::factory()->count(10)->create() then yes, I find Faker re-uses values instead of generating distinct values for each record. You can get around this by either using the unique modifier as @tisuchi suggests:

'tax' => fake()->unique()->randomFloat(2, 0, 30),

Or by returning the result from a closure. Using a closure will force the value to be re-evaluated for each individual model created:

'tax' => fn () => fake()->randomFloat(2, 0, 30),
1 like

Please or to participate in this conversation.