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

Cuid2 Laravel Package

visus/cuid2

PHP CUID2 generator for collision-resistant, secure, URL-safe IDs built for distributed systems. Uses SHA3-512 with time and entropy for scalable uniqueness. Supports instance or static usage plus identifier validation; GMP can improve performance.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require visus/cuid2
    

    Verify PHP 8.2+ and SHA3-512 support (php -r "echo hash_algos();").

  2. First Use Case: Generate a default-length (24-char) CUID in a controller:

    use Visus\Cuid2\Cuid2;
    
    $cuid = Cuid2::generate(); // e.g., "a1b2c3d4e5f6g7h8i9j0k1l2"
    return response()->json(['id' => $cuid]);
    
  3. Where to Look First:

    • src/Cuid2.php for core generation logic
    • src/Utils.php for base conversion internals
    • tests/Cuid2Test.php for validation patterns

Implementation Patterns

Core Workflows

1. ID Generation in Domain Models

// In User.php
class User {
    protected string $id;

    public function __construct() {
        $this->id = Cuid2::generate(); // Auto-generate on creation
    }

    public static function fromArray(array $data): self {
        $user = new self();
        $user->id = $data['id'] ?? Cuid2::generate(); // Fallback to CUID2
        return $user;
    }
}

2. Database Integration

// Migration
Schema::create('users', function (Blueprint $table) {
    $table->cuid2('id')->primary(); // Custom column type
    $table->string('name');
    $table->timestamps();
});

// Model
class User extends Model {
    protected $keyType = 'string';
    public $incrementing = false;
}

3. Validation Layer

use Illuminate\Validation\Rule;

$validator = Validator::make($request->all(), [
    'external_id' => [
        'required',
        Rule::custom(function ($attribute, $value, $fail) {
            if (!Cuid2::isValid($value, 24)) {
                $fail('Invalid CUID2 format.');
            }
        }),
    ],
]);

4. Batch Generation

// Generate 1000 CUIDs in bulk (e.g., for testing)
$batch = array_map(fn() => Cuid2::generate(10), range(1, 1000));

Integration Tips

  1. Service Container Binding:

    $app->bind(Cuid2::class, function () {
        return new Cuid2(24); // Default length
    });
    
  2. Custom Length Strategy:

    // config/cuid2.php
    return [
        'default_length' => env('CUID_LENGTH', 24),
        'short_length'   => 10,
    ];
    
    // Usage
    $shortId = Cuid2::generate(config('cuid2.short_length'));
    
  3. Fingerprint Customization (Advanced): Override Fingerprint singleton for environment-specific identifiers:

    $fingerprint = new \Visus\Cuid2\Fingerprint(
        env('APP_ENV'), // Custom environment
        env('HOSTNAME_OVERRIDE') // Force specific hostname
    );
    
  4. Performance Optimization:

    • Pre-instantiate Cuid2 objects in service providers:
      $app->singleton(Cuid2::class, fn() => new Cuid2());
      
    • Cache generated IDs if regeneration isn’t needed.

Gotchas and Tips

Pitfalls

  1. GMP Dependency:

    • Without ext-gmp, generation is 300x slower (fallback to pure PHP).
    • Debugging: Check php -m | grep gmp or phpinfo() for missing extension.
    • Workaround: Use shorter lengths (e.g., 10 chars) if GMP isn’t available.
  2. Counter Collisions:

    • Rapid generation (>1000 IDs/sec) may exhaust the counter.
    • Fix: Increase Counter::INCREMENT or use a distributed counter (e.g., Redis).
  3. Validation False Positives:

    • Cuid2::isValid() only checks format, not uniqueness.
    • Tip: Combine with database checks for critical systems:
      if (!Cuid2::isValid($id) || User::where('id', $id)->exists()) {
          throw new \InvalidArgumentException('Invalid or duplicate ID');
      }
      
  4. Length Constraints:

    • Minimum length is 4 chars (3 chars hash + 1 prefix).
    • Maximum is 32 chars (SHA3-512 hash limit).
    • Error: Throws \InvalidArgumentException for out-of-range lengths.
  5. Fingerprint Stability:

    • Changing gethostname() or getmypid() behavior (e.g., Docker) may alter fingerprints.
    • Tip: Use env('HOSTNAME') for consistent environments.

Debugging Tips

  1. Inspect Components:

    $cuid = new Cuid2(24);
    echo $cuid->getPrefix();      // First character (e.g., 'a')
    echo $cuid->getTimestamp();   // Unix timestamp in ms
    echo $cuid->getFingerprint(); // Binary hash of machine/process
    
  2. Benchmarking:

    $start = microtime(true);
    for ($i = 0; $i < 1000; $i++) {
        Cuid2::generate();
    }
    echo "Time: " . (microtime(true) - $start) . "s";
    
  3. Collision Testing:

    $ids = [];
    $collision = false;
    for ($i = 0; $i < 10000; $i++) {
        $id = Cuid2::generate(10);
        if (in_array($id, $ids)) {
            $collision = true;
            break;
        }
        $ids[] = $id;
    }
    echo $collision ? "Collision detected!" : "No collisions in 10k IDs.";
    

Extension Points

  1. Custom Hashing: Override Utils::base36Encode() for alternative encoding:

    class CustomCuid2 extends Cuid2 {
        protected function encodeHash(string $hash): string {
            return base64_encode($hash); // Example: Base64 instead of Base36
        }
    }
    
  2. Environment-Specific Fingerprints:

    $fingerprint = new \Visus\Cuid2\Fingerprint(
        env('APP_ENV'), // e.g., 'staging'
        env('SERVICE_NAME') // e.g., 'user-service'
    );
    
  3. Counter Reset: For testing, reset the counter singleton:

    \Visus\Cuid2\Counter::reset();
    
  4. Length Validation: Extend Cuid2 to enforce custom length rules:

    class StrictCuid2 extends Cuid2 {
        public function __construct(int $length = 24) {
            if ($length !== 24) {
                throw new \InvalidArgumentException('Only 24-char CUIDs allowed');
            }
            parent::__construct($length);
        }
    }
    

Configuration Quirks

  1. SHA3-512 Requirement:

    • Throws \RuntimeException if sha3-512 is unavailable.
    • Fix: Upgrade PHP or use a polyfill (not recommended for production).
  2. Randomness Sources:

    • Relies on random_bytes() (PHP 7.0+) or openssl_random_pseudo_bytes().
    • Tip: For testing, mock random_bytes:
      $mock = $this->createMock(Random\Randomizer::class);
      $mock->method('getBytes')->willReturn('test');
      $cuid = new Cuid2(10, $mock);
      
  3. Windows Hostname Limits:

    • gethostname() on Windows returns max 15 chars.
    • Tip: Use env('COMPUTERNAME') for consistent lengths.
  4. Time Precision:

    • Uses microtime(true) for timestamps (millisecond precision).
    • Note: For sub-millisecond precision, consider hrtime().
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.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver