Str::random
Generates a cryptographically secure random alphanumeric string of the requested length.
Str::random(int $length = 16): stringParameters
| Parameter | Type | Description |
|---|---|---|
$$lengthoptional | int= 16 | Number of characters to generate. Zero or a negative value returns an empty string. |
Return value
stringA string of the requested length drawn from A-Z, a-z and 0-9.
Errors
random_bytes throws Random\RandomException when the platform cannot supply cryptographically secure randomness.
Str::random draws bytes from random_bytes, base64-encodes them and strips +, / and =, leaving a purely alphanumeric string. That makes the output safe to drop into a URL, a filename, a header or a database column without escaping, and secure enough for tokens — it is not rand() with a character list.
Length is characters, not entropy
The alphabet has 62 symbols, so each character carries roughly 5.95 bits. The default 16 characters is about 95 bits, fine for a filename suffix or a cache-busting key. For anything a stranger could brute-force — password reset links, invitation tokens, signed URLs — use 32 or more, and remember that Laravel's own token features already generate their own values.
Making it deterministic in tests
Because the value changes on every call, an assertion against a literal will fail. Str::createRandomStringsUsing() installs a factory that receives the requested length and returns whatever you want; Str::createRandomStringsNormally() restores the real generator. The override is static and global, so restore it in tearDown or the next test inherits your fake.
Uniqueness is overwhelmingly likely but never guaranteed. If a column must be unique, put a unique index on it and retry on violation rather than trusting the odds.
Example
When to use it
- Generate a unique suffix for an uploaded filename so two uploads cannot collide.
- Create an invitation or share token stored alongside a record.
- Produce a throwaway identifier for a job, batch, or cache key in a seeder.
Frequently asked questions
Is Str::random safe for security tokens?
Yes — it is built on random_bytes, PHP's cryptographically secure source, not on rand() or uniqid(). Use 32 or more characters for anything an attacker could try to guess, such as a password reset or invitation token.
How do I make Str::random return a fixed value in a test?
Call Str::createRandomStringsUsing(fn ($length) => 'fixed-value') before the code under test, and Str::createRandomStringsNormally() in tearDown. The override is a static property, so failing to restore it affects every later test in the process.
What characters can Str::random produce?
Only A-Z, a-z and 0-9 — the base64 alphabet with +, / and = removed. That makes the output safe in URLs, filenames and headers with no escaping, but it also means it is not valid base64 and cannot be decoded.
More examples
A unique filename for an upload
The alphanumeric output needs no escaping in a path or a URL, and dropping the original name removes directory traversal and encoding problems in one step. Requires a booted application for the Storage facade and the request.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class AvatarController extends Controller
{
public function store(Request $request)
{
$file = $request->file('avatar');
// Never trust the client-supplied name.
$name = Str::random(40).'.'.$file->extension();
Storage::disk('public')->putFileAs('avatars', $file, $name);
return back();
}
}Pinning the value in a test
The factory replaces every Str::random call for the duration of the test, so the token written to the database is predictable. The tearDown is not optional — the override is a static property and would otherwise leak into every test that runs after this one.
<?php
namespace Tests\Feature;
use Illuminate\Support\Str;
use Tests\TestCase;
class InvitationTest extends TestCase
{
protected function tearDown(): void
{
Str::createRandomStringsNormally();
parent::tearDown();
}
public function test_the_invitation_token_is_stored(): void
{
Str::createRandomStringsUsing(fn () => 'fixed-token');
$this->post('/invitations', ['email' => '[email protected]']);
$this->assertDatabaseHas('invitations', [
'token' => 'fixed-token',
]);
}
}Choosing a length
Eight characters is guessable by an attacker with a botnet and is only appropriate for a non-secret identifier. Laravel itself uses 40 for API and password-reset tokens, which is the length to copy for anything security-bearing.
<?php
use Illuminate\Support\Str;
// 62 possible characters per position.
foreach ([8, 16, 32, 40] as $length) {
$bits = $length * log(62, 2);
printf("%2d chars ≈ %5.1f bits of entropy\n", $length, $bits);
}
// 8 chars ≈ 47.6 bits of entropy
// 16 chars ≈ 95.3 bits of entropy
// 32 chars ≈ 190.6 bits of entropy
// 40 chars ≈ 238.2 bits of entropy
Discussion