str_shuffle
Randomly shuffles the characters of a string and returns the result as a new string.
str_shuffle(string $string): string- Added in PHP 4.3.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string to shuffle. |
Return value
stringThe shuffled string.
Changelog
- PHP 7.1.0The internal randomization algorithm changed from the libc rand function to the Mersenne Twister, so seeded output differs from earlier versions.
str_shuffle returns a new string containing exactly the same bytes as the input, in a random order. The original string is not modified, and the length is always unchanged.
When to reach for it
It is handy for demos, word games, anagram puzzles, randomising the order of a fixed set of characters, or scrambling a captcha string. Anywhere the goal is visual randomness rather than security, it does the job in one call.
What trips people up
Two problems bite people constantly. First, this is not cryptographically secure. It draws from the global Mersenne Twister, so its output is predictable to anyone who can observe or guess the generator state. Never use it for passwords, session tokens, reset links or API keys — use random_bytes(), random_int(), or Random\Randomizer with Random\Engine\Secure.
Second, shuffling is a permutation, not sampling with replacement. substr(str_shuffle($alphabet), 0, 8) can never repeat a character, which shrinks the keyspace far below what people assume and makes the result easy to spot.
It also works on bytes, so shuffling a UTF-8 string splits multi-byte characters apart and produces invalid text. Split with mb_str_split() and shuffle() the array instead.
Example
When to use it
- Scramble letters for an anagram or word-jumble game
- Randomise the character order in a captcha image string
- Produce throwaway sample data for a demo or test fixture
Frequently asked questions
Is str_shuffle safe for generating passwords or tokens?
No. It uses the global Mersenne Twister, which is predictable, and it can never repeat a character. Use random_bytes(), random_int(), or Random\Randomizer with Random\Engine\Secure instead.
Does str_shuffle change the original string?
No. PHP strings are values, so str_shuffle returns a new shuffled string and leaves the variable you passed in untouched.
Why does str_shuffle break my UTF-8 text?
It shuffles bytes, not characters, so multi-byte sequences get split apart. Use mb_str_split() to get an array of characters, shuffle() that array, then implode() it.
More examples
Repeatable shuffles with a seed
Seeding the global Mersenne Twister with the same value makes str_shuffle produce identical output, which is exactly why it is unsafe for tokens: the sequence is reproducible from the seed. It is useful for deterministic tests.
<?php
mt_srand(1234);
$a = str_shuffle('ABCDEFGH');
mt_srand(1234);
$b = str_shuffle('ABCDEFGH');
echo $a, "\n";
var_dump($a === $b); // bool(true)Why it is a bad password generator
The unique-character count is always 8 because a shuffle cannot repeat a character — "aabbccdd" is unreachable. The random_bytes version can repeat characters and comes from a cryptographically secure source.
<?php
$pool = 'abcdefghijklmnopqrstuvwxyz';
$token = substr(str_shuffle($pool), 0, 8);
echo $token, "\n";
echo count(array_unique(str_split($token))), "\n"; // always 8
$secure = bin2hex(random_bytes(4));
echo $secure, "\n";Shuffling multi-byte text safely
Splitting into characters first and shuffling the array keeps every accented letter intact; the var_dump confirms the character count survives. Calling str_shuffle directly on this string would break é and ö into stray bytes.
<?php
$s = 'héllo wörld';
$chars = mb_str_split($s);
shuffle($chars);
echo implode('', $chars), "\n";
var_dump(mb_strlen(implode('', $chars)) === mb_strlen($s));
Discussion