srand
Seeds PHP's general-purpose random number generator so rand() produces a repeatable sequence.
srand(?int $seed = null, int $mode = MT_RAND_MT19937): void- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$seedoptional | ?int= null | Fills the generator state using a linear congruential generator seeded with this value, interpreted as an unsigned 32-bit integer. If omitted or null, a random unsigned 32-bit integer is used instead. |
$modeoptional | int= MT_RAND_MT19937 | The Mersenne Twister variant to use. MT_RAND_MT19937 is the correct implementation; MT_RAND_PHP reproduces the broken pre-7.1 variant and exists only for backwards compatibility. |
Return value
voidNo value is returned.
Errors
Passing a value for mode other than MT_RAND_MT19937 or MT_RAND_PHP throws a ValueError. Nothing else raises an error.
Changelog
- PHP 8.3.0The seed parameter is now nullable, so srand(null) is equivalent to calling srand() with no arguments.
- PHP 7.1.0srand() became an alias of mt_srand(). Seeding now drives the Mersenne Twister, and the sequence produced by a given seed changed completely from PHP 7.0 and earlier.
srand() pins the internal state of the generator behind rand(). The same seed gives the same sequence of numbers every time, which is the entire point: it turns random output into repeatable output.
When to reach for it
Use it when a test, a fixture generator, or a procedural level builder must produce identical results on every run. Seed once at the start, then let the generator run.
Do not use it to "improve" randomness. PHP seeds the generator automatically the first time you draw a number, and that automatic seed is better than anything you are likely to pass in. Seeding with time() or a request counter actively makes output more predictable.
What trips people up
Since PHP 7.1 srand() is a straight alias of mt_srand(), and it seeds one shared engine. That engine also powers shuffle(), str_shuffle() and array_rand(), so seeding in one place quietly makes all of them deterministic too.
The sequence for a given seed is also not a stable contract across PHP releases. Treat seeded output as "repeatable within this process", never as a value you commit to a snapshot test. And a seeded generator is never secure — use random_int() for anything an attacker should not be able to predict.
Example
When to use it
- Make a test suite that generates fake orders produce the same data on every CI run
- Reproduce a bug report by replaying the exact random sequence the user hit
- Generate a procedural map or dungeon that a player can share with a seed string
- Build stable demo data for a screenshot or documentation example
Frequently asked questions
Do I need to call srand() before using rand()?
No. PHP seeds the generator automatically on first use, and its automatic seed is stronger than any value you would pass manually. Only call srand() when you deliberately want a repeatable sequence.
What is the difference between srand and mt_srand?
Nothing since PHP 7.1 — srand() is an alias of mt_srand() and they seed the same Mersenne Twister state. Before 7.1 srand() seeded a separate, weaker libc generator used by rand().
Is a seeded rand() secure enough for tokens or passwords?
No, and neither is an unseeded one. Anyone who observes a few outputs can recover the Mersenne Twister state and predict the rest; use random_int() or random_bytes() for anything security-related.
More examples
Deterministic shuffle for tests
shuffle() draws from the same engine srand() seeds, so re-seeding with 2024 replays the exact same permutation. The output shows one shuffled deck and true, which is why a seeded shuffle is safe to assert on inside a single test run.
<?php
$deck = ['ace', 'king', 'queen', 'jack', 'ten'];
$again = ['ace', 'king', 'queen', 'jack', 'ten'];
srand(2024);
shuffle($deck);
srand(2024);
shuffle($again);
print_r($deck);
echo 'identical: ', var_export($deck === $again, true), "\n";Re-seeding with null goes back to unpredictable
The first comparison prints true because seed 7 always regenerates the same first draw. The second prints false, because calling srand() with no argument throws away the fixed seed and picks a random 32-bit one — this is how you leave a deterministic block and return to normal behaviour.
<?php
srand(7);
$a = rand();
srand(); // null seed: pick a fresh random seed
$b = rand();
srand(7);
$c = rand();
echo 'a === c (same seed): ', var_export($a === $c, true), "\n";
echo 'a === b (re-seeded): ', var_export($a === $b, true), "\n";
Discussion