jenssegers/optimus
Optimus obfuscates internal numeric IDs using Knuth’s integer hash. Like Hashids but returns fast, reversible integers (not strings). Generate prime/inverse/random via a CLI command, then encode/decode IDs consistently across your app.
id columns) with non-sequential integers, addressing:
/users/1, /users/2)./users/1535832388).Optimus in controllers/middleware.retrieved/saved events.| Risk | Mitigation |
|---|---|
| Prime/Inverse Errors | Use php artisan optimus:spark to auto-generate primes; document primes in config. |
| 32-bit Systems | Require GMP extension (document in README; test on CI). |
| ID Collisions | Knuth’s method minimizes collisions; validate with edge cases (e.g., max DB ID range). |
| Migration Complexity | Backfill IDs via a Laravel migration (e.g., Schema::table). |
| Caching Overhead | Singleton instance avoids per-request instantiation. |
unsignedBigInt vs. int)? Optimus defaults to 2147483647.Optimus::create($primePerTenant))?Optimus as a singleton (e.g., App\Providers\OptimusServiceProvider).icanhazstring/optimus-middleware).retrieved/saved events for auto-encoding.new Optimus($prime, $inverse, $random)) in services/controllers.return response()->json(['id' => $optimus->encode($id)])).optimus_id column to DB:
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('optimus_id')->nullable();
});
DB::table('users')->update([
'optimus_id' => DB::raw('(SELECT encode(id) FROM optimus WHERE id = users.id)')
]);
Route::get('/users/{optimusId}', function ($optimusId) {
$userId = $optimus->decode($optimusId);
return User::find($userId);
})->middleware('decode.optimus');
/users/{originalId} endpoints with redirects.| Component | Notes |
|---|---|
| PHP Versions | Supports PHP 8.0+ (check composer.json; drop PHP 7.x support if needed). |
| Laravel | Tested up to Laravel 11; ensure config/app.php includes OptimusServiceProvider. |
| Databases | No schema changes; works with MySQL, PostgreSQL, etc. |
| 32-bit Systems | Requires GMP extension (document in README; test on CI). |
| Existing Clients | Gradual migration: expose both old/new IDs during transition. |
php artisan optimus:spark
Store primes in .env (e.g., OPTIMUS_PRIME=1580030173).// App\Providers\OptimusServiceProvider.php
$this->app->singleton(Optimus::class, fn() => new Optimus(
config('optimus.prime'),
config('optimus.inverse'),
config('optimus.random')
));
{id} with {optimusId} in routes.optimus_id column./users/{originalId} URLs..env or database (never hardcode).php artisan optimus:spark).optimus->decode() in Tinker/debug mode.toOriginalId() method to models for debugging:
public function getOriginalIdAttribute() {
return $this->optimus->decode($this->optimus_id);
}
| Failure | Impact | Mitigation |
|---|---|---|
| Invalid ID Decoding | 404 errors for clients. | Add middleware to catch decode failures; log and redirect gracefully. |
| Prime/Inverse Mismatch | Decoding fails across deployments. | Store primes in a central config (e.g., database, Vault). |
| GMP Extension Missing | Fails on 32-bit systems. | Document requirement; use Docker with GMP-enabled PHP images. |
| ID Collisions | Rare but possible with large ranges. | Validate primes against max ID range; use larger primes if needed. |
OPTIMUS.md to the repo with:
How can I help you explore Laravel packages today?