Randomness

Randomness: rand, mt_rand and the Random Extension

rand() has been an alias of mt_rand() since PHP 7.1: one global Mersenne Twister, fast but predictable. random_int() and random_bytes() (PHP 7.0) read the operating system's secure generator. The Random extension (PHP 8.2) separates the algorithm, an engine, from Random\Randomizer, which turns its output into integers, floats, bytes and shuffles.

Secure random values, a reproducible seeded sequence and the legacy API (random.php)PHP
<?php
use Random\{Randomizer, IntervalBoundary};
use Random\Engine\Xoshiro256StarStar;
$r = new Randomizer();                        // default engine: Random\Engine\Secure (CSPRNG)
echo get_class($r->engine), ' ', $r->getInt(1, 6), ' ',
    $r->getBytesFromString('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', 10), ' ',   // no 0/O or 1/I
    json_encode($r->shuffleArray(['a', 'b', 'c', 'd'])), ' ',
    round($r->getFloat(0, 1, IntervalBoundary::ClosedOpen), 4), "\n";
echo random_int(100000, 999999), ' ', bin2hex(random_bytes(16)), "\n";
$seeded = fn() => new Randomizer(new Xoshiro256StarStar(20260923));   // reproducible
[$a, $b] = [$seeded(), $seeded()];
echo json_encode([$a->getInt(1, 100), $a->getInt(1, 100)]), ' ',
    json_encode([$b->getInt(1, 100), $b->getInt(1, 100)]), ' ',
    json_encode($a->pickArrayKeys(['x' => 1, 'y' => 2, 'z' => 3], 2)), ' | ';
mt_srand(42);                                 // the legacy global Mt19937 generator
echo mt_rand(1, 100), ' ', rand(1, 100), ' ', mt_getrandmax(), "\n";
Output
Random\Engine\Secure 1 YXDNGT5MT7 ["b","a","c","d"] 0.7686
105738 e7f06880306d9722efab543f6ab7e9e5
[44,31] [44,31] ["x","y"] | 43 68 2147483647

The first two lines change on every run; the third never does. Of the engines Secure, Mt19937, PcgOneseq128XslRr64 and Xoshiro256StarStar, only Secure is fit for secrets: tokens and reset codes never come from rand(), mt_rand() or uniqid(). Seeded engines give reproducible test data without touching the global state. getFloat() and getBytesFromString() (PHP 8.3) replace lcg_value(), deprecated in 8.4. CSRF Tokens and Auth Hardening build tokens this way.