Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Random Polyfill Laravel Package

arokettu/random-polyfill

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require arokettu/random-polyfill
    
    • No additional configuration is required. The package auto-detects PHP 8.2+ and falls back to native ext-random if available.
  2. First Use Case: Generate a cryptographically secure random integer between 1 and 100:

    use Random\Engine\Secure;
    use Random\Randomizer;
    
    $engine = new Secure();
    $randomizer = new Randomizer($engine);
    $randomInt = $randomizer->getInt(1, 100);
    
  3. Where to Look First:

    • Official Documentation: Covers all classes, methods, and compatibility details.
    • PHP 8.2 Random Extension Manual: Reference for native API behavior (this polyfill mirrors it).
    • Source Code: The package is minimal and well-structured. Key files:
      • src/Randomizer.php: Core randomness logic.
      • src/Engine/: All available PRNG engines (e.g., Secure.php, Mt19937.php).

Implementation Patterns

Usage Patterns

1. Basic Randomness (Replacing rand()/mt_rand)

use Random\Engine\Mt19937;
use Random\Randomizer;

$engine = new Mt19937();
$randomizer = new Randomizer($engine);

// Replace rand(1, 100)
$value = $randomizer->getInt(1, 100);

// Replace mt_rand()
$value = $randomizer->getInt();

2. Cryptographically Secure Operations

use Random\Engine\Secure;
use Random\Randomizer;

$engine = new Secure();
$randomizer = new Randomizer($engine);

// Generate a secure token
$token = bin2hex($randomizer->getBytes(16));

// Shuffle an array securely
$array = [1, 2, 3, 4, 5];
$randomizer->shuffleArray($array);

3. Advanced Engines for Performance

use Random\Engine\PcgOneseq128XslRr64;
use Random\Randomizer;

$engine = new PcgOneseq128XslRr64();
$randomizer = new Randomizer($engine);

// Faster than Mt19937 for high-throughput scenarios
$randomInt = $randomizer->getInt();

4. Serialization/Deserialization (PHP 7.4+ Compatibility)

$randomizer = new Randomizer(new Secure());
$serialized = serialize($randomizer);
$unserialized = unserialize($serialized); // Works in PHP 7.4+

Workflows

Migrating from rand()/mt_rand

  1. Replace calls:
    • rand($min, $max)$randomizer->getInt($min, $max)
    • mt_rand()$randomizer->getInt()
  2. Update seeding (if needed):
    $engine = new Mt19937();
    $engine->seed(time()); // Optional: Explicit seeding
    $randomizer = new Randomizer($engine);
    
  3. Test edge cases:
    • Large ranges (e.g., getInt(1, PHP_INT_MAX)).
    • Serialization/deserialization (if state persistence is required).

Integrating with Laravel

  1. Service Provider Binding:
    // app/Providers/AppServiceProvider.php
    use Illuminate\Support\ServiceProvider;
    use Random\Engine\Secure;
    use Random\Randomizer;
    
    class AppServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(Randomizer::class, function ($app) {
                return new Randomizer(new Secure());
            });
        }
    }
    
  2. Usage in Controllers/Jobs:
    use Random\Randomizer;
    
    class UserController extends Controller
    {
        public function __construct(private Randomizer $randomizer) {}
    
        public function generateToken()
        {
            return bin2hex($this->randomizer->getBytes(16));
        }
    }
    
  3. Helper Methods:
    // app/Helpers/RandomHelper.php
    if (!function_exists('random_bytes')) {
        function random_bytes(int $length): string
        {
            $randomizer = app(Randomizer::class);
            return $randomizer->getBytes($length);
        }
    }
    

Custom Engines

Extend the Random\Engine interface for domain-specific needs:

use Random\Engine;
use Random\Engine\Secure;

class CustomEngine implements Engine
{
    public function getBytes(int $length): string
    {
        // Implement custom logic (e.g., combine Secure + Mt19937)
        $secure = new Secure();
        return $secure->getBytes($length);
    }

    public function nextInt(): int
    {
        // Implement custom logic
        return (int) hexdec(bin2hex($this->getBytes(4)));
    }
}

Integration Tips

  1. PHP 8.2+ Fallback: The package automatically uses native ext-random if available. No manual checks are needed.

  2. Performance Considerations:

    • For cryptographic use: Always use Secure engine.
    • For non-cryptographic use: Mt19937 or PcgOneseq128XslRr64 (faster on 64-bit systems).
    • Avoid getBytes() in loops: Pre-generate bytes if possible (e.g., getBytes(1000) once, then slice).
  3. Thread Safety: All engines are thread-safe (stateless or internally synchronized). Safe for use in concurrent environments (e.g., Laravel queues).

  4. Testing:

    • Use Mt19937 with a fixed seed for deterministic tests:
      $engine = new Mt19937();
      $engine->seed(42); // Fixed seed
      $randomizer = new Randomizer($engine);
      
    • Verify edge cases:
      • getInt(PHP_INT_MIN, PHP_INT_MAX).
      • getBytes(0) or getBytes(PHP_INT_MAX).
  5. Legacy PHP 7.1:

    • GMP Extension: Strongly recommended for performance (used internally for large-number operations).
    • 32-bit Systems: Some engines (e.g., Mt19937) may have reduced performance or integer overflow risks. Use PcgOneseq128XslRr64 as an alternative.

Gotchas and Tips

Pitfalls

  1. Serialization Warnings:

    • arrayPickKeys() may throw warnings in non-cryptographic engines (e.g., Mt19937). Suppress with:
      $randomizer->arrayPickKeys($array, $num, false); // Disable warning
      
    • Fix: Use Secure engine if you need arrayPickKeys() without warnings.
  2. Integer Overflow in 32-bit PHP:

    • Mt19937 may produce incorrect results for very large ranges (e.g., getInt(1, PHP_INT_MAX)).
    • Workaround: Use PcgOneseq128XslRr64 or constrain ranges to < 2^31.
  3. PHP 7.1 Limitations:

    • No random_int(): This polyfill does not replace random_int(). Use Secure engine + getInt() instead.
    • GMP Dependency: Some operations (e.g., large-number generation) will be slower without GMP.
  4. Engine-Specific Quirks:

    • Secure engine throws RandomException (not Exception) for errors.
    • Xoshiro256StarStar is faster than Mt19937 but less random for cryptographic use.
  5. PHP 8.2+ Auto-Detection:

    • The package does nothing in PHP 8.2+. If you need to force the polyfill (e.g., for testing), set:
      putenv('PHP_RANDOM_POLYFILL_FORCE=1');
      

Debugging Tips

  1. Verify Engine Behavior:

    $engine = new Secure();
    $bytes = $engine->getBytes(16);
    var_dump(hex2bin($bytes)); // Should be 16 truly random bytes
    
  2. **Check for Side Effects

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ilhamsyabani/laravel-volt-starter
thethunderturner/filament-latex
ghostcompiler/laravel-querybuilder
webrek/laravel-telescope-mongodb
anousss007/blatui
zatona-eg/zatona-eg-api
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat