Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kfriars@gmail.com's avatar

Setting Faker seed() producing non-deterministic results

Hello, I am using faker to help seed some data, but want it to produce the same generated data on every run. I have created a SeedingServiceProvider where in the register method I have:

    $this->app->singleton(
        Faker::class,
        function () {
            $faker = FakerFactory::create('en_CA');
            $faker->seed(2);
            return $faker;
        }
    );

I have verified that the Faker instance is resolved only once and by putting debug statements inside of the Faker\Generator class that the $seed is always set to 2. However, I am getting different results on every seeding.

Anyone have any thoughts? If not I will take this to Faker Github issues.

Thanks for the help!

Environment

Laravel 5.6 on PHP 7.2

Further Investigation

Have also tried using $this->app->bind() and still non-deterministic.

I thought this was solved, by removing a different mt_srand call from my codebase, but the issue is back...

The Issue Explained Some other 3rd party dependency, or some calls to something rand() is ruining the determinism. I have created a PR and a fork, to create a durable deterministic mode using Faker's seed.

0 likes
5 replies
bugsysha's avatar

By using singleton you are not telling functions/methods within faker library to be called only once and to remember return values. You are only limiting the number of times how many new instances of that class can be created.

Then hardcode all the values in *Factory.php files and you are good.

kfriars@gmail.com's avatar

Thanks for the help BUGSYSHA.

I am aware the functions and methods of faker are not called only once. By setting seed() on the instance, you are actually just setting the seed for php randomness using mt_srand. By doing so, if nothing else messes with mt_srand, faker will always produce consistent results. The issue is that if anything else sets mt_srand in a non-deterministic way ie mt_srand(microtome()) then faker no longer maintains its determinism. This is due to php's random functions using the seed globally.

I do not want to hard code the values in my factory methods.

I have forked faker with a solution and posted a PR you can view here.

https://github.com/fzaninotto/Faker/issues/1913

bugsysha's avatar

@kfriars@gmail.com can you show an example here cause I'm not sure that I understand now. Let's say we have that default UserFactory that comes with Laravel. What would be the output from that factory? Or give some other example.

kfriars@gmail.com's avatar

Sure thing.

So faker is used to generate "random" values for testing purposes generally speaking.

Say your user model has the following fields: (email, first_name, last_name, gender, date_of_birth, phone)

In the model factory you could use:

$factory->define(App\Models\User::class, function (Faker $faker) {
    return [
        'email' => $faker->unique()->safeEmail,
        'first_name' => $faker->firstName,
        'last_name' => $faker->lastName,
        'gender' => $faker->randomElement(['male', 'female', 'other']),
        'date_of_birth' => $faker->dateTimeBetween('-70 years', '-18 years'),
        'phone' => $faker->phoneNumber,
    ];
});

Every time we seed our database, different values will be generated since we are not setting $faker->seed($seedNumber). If we did set the seed at the top of this factory, we would always get the same values for these fields. This is helpful for testing because you can make assertions about what data to expect.

Now imagine you have many different factories and many different seeders, I had two options.

  1. Put $faker->seed() all over my code to ensure determinism (Even this may not work in some cases)

  2. Make Faker a singleton so that the same instance of faker is being used, and the seed value is set before each call to a faker method

Now, Option 2 did not work because using $faker->seed() does not actually set a property of the instance of faker, it seeds php's random number generator which it uses to create "randomness". So other parts of your code, or your dependencies code can mess with php's number generator seed, and if you call faker at any point after it will become non-deterministic (different results on each seeding).

The solution in my PR is kind of a hack but achieves the desired results. By calling $faker->seed(2, true), you can set a durable mode. Faker uses the __get() and __call() magic methods where we can set mt_srand every time by incrementing the seed passed in. Now every call to any faker method anywhere in your code will have the desired results of determinism with "randomness".

I have also realized, that this should not be made a singleton, but just bound to the service container, so that changes in one class do not spill over to another.

bugsysha's avatar

Can you provide some tests so I can see what are the benefits of having repeatable data? Are they any cleaner?

Please or to participate in this conversation.