symfony/polyfill-uuid
Symfony Polyfill for UUID brings uuid_* functions to PHP environments that don’t have the uuid extension installed. It lets applications use common UUID helpers consistently across PHP versions, matching Symfony’s polyfill approach and staying lightweight and MIT licensed.
Installation:
Add the package via Composer (often auto-included with Laravel’s symfony/polyfill bundle):
composer require symfony/polyfill-uuid
Note: Laravel 8+ includes this polyfill by default in its symfony/polyfill package.
First Use Case: Replace custom UUID generation with built-in functions:
// Generate a v4 UUID (RFC 4122 compliant)
$uuid = uuid_generate_v4(); // e.g., "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
// Laravel Str facade (if available)
$uuid = Str::uuid();
Where to Look First:
$table->uuid('id')->default(uuid_generate_v4());
Str::uuid() for default values or factories:
$model->uuid = Str::uuid();
Laravel-Centric Workflows:
Schema::create('users', function (Blueprint $table) {
$table->uuid('id')->default(uuid_generate_v4());
$table->string('name');
$table->timestamps();
});
User::factory()->create(['uuid' => Str::uuid()]);
return response()->json(['uuid' => Str::uuid()]);
Symfony Integration:
Symfony\Component\Uid\Uuid if available):
use Symfony\Component\Uid\Uuid;
$uuid = Uuid::v4()->toRfc4122();
Uid component is later adopted.Cross-Environment Consistency:
ext-uuid:
// Lambda function example
return [
'id' => uuid_generate_v4(),
'data' => $request['payload']
];
Legacy Code Modernization:
ramsey/uuid, voku/uuid) with polyfill functions:
// Before
$uuid = \Ramsey\Uuid\Uuid::uuid4()->toString();
// After
$uuid = uuid_generate_v4();
Leverage Laravel’s Str Facade:
If using Laravel, prefer Str::uuid() for consistency:
use Illuminate\Support\Str;
$uuid = Str::uuid(); // Uses polyfill under the hood
Database Schema:
Use uuid() in migrations for PostgreSQL/MySQL 8+:
$table->uuid('id')->default(uuid_generate_v4());
Tip: For SQLite, use string(36) and validate UUIDs in application logic.
Testing: Mock UUID generation in tests to avoid flakiness:
// In a test case
UUID::shouldReceive('generate')
->once()
->andReturn('mock-uuid-123');
Performance Considerations:
ext-uuid in PHP 8.0+ for native performance if possible.Entropy Validation:
Ensure random_bytes() has sufficient entropy in CI/CD or containers:
# Docker example
docker run --cap-add=SYS_RANDOM ...
Entropy Issues:
random_bytes() may fail in low-entropy environments (e.g., Docker without --cap-add=SYS_RANDOM or CI/CD pipelines).random_bytes() in tests:
// Mock in PHPUnit
$this->replace('random_bytes', fn() => random_bytes(16));
PHP Version Quirks:
random_bytes() support (though Laravel typically targets PHP 7.4+).openssl_random_pseudo_bytes() as a fallback:
if (!function_exists('random_bytes')) {
$bytes = openssl_random_pseudo_bytes(16);
}
UUID Validation:
if (!Uuid::isValid($uuid)) { // Use ramsey/uuid for validation
throw new \InvalidArgumentException('Invalid UUID');
}
Laravel-Specific Gotchas:
Str::uuid() may not be available in older Laravel versions (< 5.7).uuid_generate_v4() directly or upgrade Laravel.Database Compatibility:
string(36) and validate UUIDs in models:
protected $casts = [
'uuid' => 'string',
];
public function validateUuidAttribute($value) {
return Uuid::isValid($value) ?: throw new \InvalidArgumentException();
}
Check UUID Format:
Ensure generated UUIDs match RFC 4122 (e.g., 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed):
$uuid = uuid_generate_v4();
assert(preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid));
Performance Profiling:
Compare polyfill vs. native ext-uuid:
# Benchmark in Laravel
php artisan tinker
>>> $start = microtime(true);
>>> for ($i = 0; $i < 10000; $i++) uuid_generate_v4();
>>> echo microtime(true) - $start;
Entropy Testing:
Verify random_bytes() in CI/CD:
$bytes = random_bytes(16);
if (strlen($bytes) !== 16) {
throw new \RuntimeException('Insufficient entropy');
}
Custom UUID Generation:
Extend the polyfill’s logic by wrapping uuid_generate_v4():
function custom_uuid() {
$uuid = uuid_generate_v4();
return strtoupper($uuid); // Example: Uppercase UUIDs
}
Fallback for random_bytes:
Implement a custom fallback for restricted environments:
if (!function_exists('random_bytes')) {
function random_bytes($length) {
return openssl_random_pseudo_bytes($length);
}
}
Integration with ramsey/uuid:
Use the polyfill for basic generation but ramsey/uuid for validation:
$uuid = uuid_generate_v4();
if (!\Ramsey\Uuid\Uuid::isValid($uuid)) {
// Handle invalid UUID (unlikely but possible)
}
Laravel Service Provider: Bind a custom UUID generator in Laravel’s service container:
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->bind('uuid-generator', function() {
return new class {
public function generate() {
return uuid_generate_v4();
}
};
});
}
No Configuration Required:
The polyfill auto-loads and requires no manual setup in config/app.php.
Laravel’s Str Facade:
Ensure Str::uuid() is available by including the Illuminate\Support\Str facade:
use Illuminate\Support\Str;
PHP Extensions:
The polyfill gracefully falls back to native functions if ext-uuid is installed:
How can I help you explore Laravel packages today?