rand

Generates a pseudo-random integer, optionally between an inclusive minimum and maximum.

Signature
rand(): int
rand(int $min, int $max): int
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$minoptionalintThe lowest value that can be returned. Must be supplied together with max; with no arguments the range starts at 0.
$maxoptionalintThe highest value that can be returned, inclusive. Must be supplied together with min; with no arguments it defaults to getrandmax().

Return value

intA pseudo-random integer between min and max inclusive, or between 0 and getrandmax() when called with no arguments.

Errors

As an alias of mt_rand(), throws a ValueError as of PHP 8.0.0 if max is less than min.

Changelog

  • PHP 7.2.0A modulo bias bug was fixed, so sequences generated from a specific seed may differ from PHP 7.1 on 64-bit machines.
  • PHP 7.1.0rand() became an alias of mt_rand(), switching from the platform libc generator to Mersenne Twister. srand() likewise became an alias of mt_srand().

Since PHP 7.1, rand() is simply an alias of mt_rand(). They share one global Mersenne Twister state, so seeding with srand() or mt_srand() affects both identically, and getrandmax() and mt_getrandmax() both return 2147483647. Before 7.1 rand() used the platform's libc generator, which had visibly poor quality on some systems — that history is why so much old advice says "use mt_rand() instead". On modern PHP that advice is now purely stylistic.

It is not secure

Mersenne Twister is deterministic, and its internal state can be reconstructed from a modest run of consecutive outputs. Never use rand() for password reset links, session tokens, API keys, one-time codes or anything an attacker benefits from guessing. random_int() has the same two-argument signature and draws from the operating system's cryptographic source; switching is a one-word change.

Range details

Both bounds are inclusive, so rand(1, 10) can return 10, and indexing an array needs rand(0, count($a) - 1). Pass both arguments or neither. Since PHP 8.0 an inverted range throws a ValueError rather than returning false.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Pick a random index into an array of demo or placeholder content
  • Roll dice or draw a random card in a simulation
  • Add randomised jitter to a retry backoff interval
  • Sample a subset of rows for a quick statistical check

Frequently asked questions

What is the difference between rand() and mt_rand()?

Since PHP 7.1 there is none - rand() is an alias of mt_rand() and both use the same global Mersenne Twister state. Before 7.1, rand() used the platform's libc generator, which produced lower-quality output on some systems.

Is rand() safe for generating passwords or tokens?

No. Its output is deterministic and predictable from a run of previous values, so it must never produce tokens, passwords, session IDs or reset links. Use random_int() or random_bytes() instead.

Does rand(1, 10) ever return 10?

Yes, both bounds are inclusive. When picking an array index you therefore need rand(0, count($array) - 1), or simply use array_rand().

More examples

Inclusive bounds and array indexing

rand(0, count($a)) would occasionally produce an index one past the last element and emit an undefined-offset warning. The seeded tally shows the corrected range spreading roughly 300 picks across each of the three colours.

Example · php
<?php
$colours = ['red', 'green', 'blue'];

// Correct: subtract 1 because max is inclusive
echo $colours[rand(0, count($colours) - 1)], "\n";

mt_srand(5);
$counts = array_fill_keys($colours, 0);
for ($i = 0; $i < 900; $i++) {
    $counts[$colours[rand(0, 2)]]++;
}
print_r($counts);

Swapping to random_int() for anything sensitive

Both loops build an eight-digit code, but only the second is unguessable. random_int() takes the same min and max arguments as rand(), so hardening this kind of code is a direct substitution.

Example · php
<?php
// Predictable - fine for a demo, unsafe for a token
$weak = '';
for ($i = 0; $i < 8; $i++) { $weak .= rand(0, 9); }
echo "demo code:  $weak\n";

// Cryptographically secure, same call shape
$strong = '';
for ($i = 0; $i < 8; $i++) { $strong .= random_int(0, 9); }
echo "real token: $strong\n";
echo bin2hex(random_bytes(8)), "\n";

Inverted ranges throw since PHP 8.0

Before PHP 8.0 an inverted range raised a warning and returned false, which silently poisoned later arithmetic. Now it throws, so sort the bounds with min() and max() when they come from user input.

Example · php
<?php
try {
    echo rand(100, 1), "\n";
} catch (ValueError $e) {
    echo 'ValueError: ', $e->getMessage(), "\n";
}

// Normalise the bounds instead
$lo = 100; $hi = 1;
$v = rand(min($lo, $hi), max($lo, $hi));
var_dump($v >= 1 && $v <= 100);  // bool(true)

Discussion

  • Be the first to comment on this lesson.