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

Optimus Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the Package:

    composer require jenssegers/optimus
    

    For 32-bit systems, install the GMP extension:

    apt-get install php8.1-gmp  # Adjust version as needed
    
  2. Generate Keys: Run the Artisan command to generate a prime, inverse, and random number:

    php artisan optimus:spark
    

    Example output:

    Prime: 2123809381
    Inverse: 1885413229
    Random: 146808189
    

    Save these values for use in your application.

  3. Register the Service Provider: Add the following to config/app.php:

    App\Providers\OptimusServiceProvider::class,
    

    Create the provider:

    namespace App\Providers;
    
    use Jenssegers\Optimus\Optimus;
    use Illuminate\Support\ServiceProvider;
    
    class OptimusServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(Optimus::class, function ($app) {
                return new Optimus(2123809381, 1885413229, 146808189); // Replace with your generated values
            });
        }
    }
    
  4. First Use Case: Encode and decode an ID in a controller:

    use Jenssegers\Optimus\Optimus;
    
    class UserController extends Controller
    {
        public function show($id, Optimus $optimus)
        {
            $originalId = $optimus->decode($id);
            $user = User::find($originalId);
            return view('user.show', compact('user'));
        }
    }
    

Implementation Patterns

Dependency Injection

Leverage Laravel’s DI to inject Optimus into controllers, services, or middleware:

// Controller
public function index(Optimus $optimus) {
    $encodedIds = $optimus->encode(1); // Example
    return response()->json(['encoded_id' => $encodedIds]);
}

Middleware for Automatic Decoding

Create middleware to decode IDs in routes:

namespace App\Http\Middleware;

use Closure;
use Jenssegers\Optimus\Optimus;

class DecodeIdMiddleware
{
    public function __construct(protected Optimus $optimus) {}

    public function handle($request, Closure $next)
    {
        $id = $request->route('id');
        $request->merge(['id' => $this->optimus->decode($id)]);
        return $next($request);
    }
}

Register in app/Http/Kernel.php:

protected $middleware = [
    \App\Http\Middleware\DecodeIdMiddleware::class,
];

Eloquent Model Integration

Extend Eloquent models to auto-encode IDs in responses:

use Jenssegers\Optimus\Optimus;

class User extends Model
{
    public function getIdAttribute($value)
    {
        return app(Optimus::class)->encode($value);
    }
}

API Response Transformation

Use Laravel’s App\Services\ResolvesApplication to encode IDs in API responses:

namespace App\Services;

use Jenssegers\Optimus\Optimus;
use Illuminate\Http\Resources\Json\JsonResource;

class EncodeIds extends JsonResource
{
    public function toArray($request)
    {
        $array = parent::toArray($request);
        $optimus = app(Optimus::class);
        if (isset($array['id'])) {
            $array['id'] = $optimus->encode($array['id']);
        }
        return $array;
    }
}

Batch Processing

Decode/encode IDs in bulk for migrations or data exports:

use Jenssegers\Optimus\Optimus;

$optimus = app(Optimus::class);
$users = User::all()->pluck('id');
$encodedIds = $users->map(fn($id) => $optimus->encode($id));

Gotchas and Tips

Pitfalls

  1. Prime/Inverse Consistency:

    • Issue: Using different primes/inverses across environments will cause decoding failures.
    • Fix: Store these values in .env or a secure config file:
      OPTIMUS_PRIME=2123809381
      OPTIMUS_INVERSE=1885413229
      OPTIMUS_RANDOM=146808189
      
    • Load them dynamically in the OptimusServiceProvider:
      return new Optimus(
          config('optimus.prime'),
          config('optimus.inverse'),
          config('optimus.random')
      );
      
  2. ID Range Limits:

    • Issue: Optimus assumes IDs are positive integers below 2147483647. Negative IDs or zero will fail.
    • Fix: Validate IDs before encoding/decoding:
      if ($id <= 0 || $id >= 2147483647) {
          throw new \InvalidArgumentException('ID out of range');
      }
      
  3. 32-bit Systems:

    • Issue: Without the GMP extension, large primes may cause overflow errors.
    • Fix: Document the requirement in your README or DEPLOYMENT.md:
      ## Requirements
      - PHP GMP extension (for 32-bit systems)
      
  4. Collision Risk:

    • Issue: Knuth’s method is collision-resistant, but edge cases (e.g., max integer values) may cause issues.
    • Fix: Test with your maximum expected ID:
      $maxId = User::max('id');
      $encoded = $optimus->encode($maxId);
      $decoded = $optimus->decode($encoded);
      assert($maxId === $decoded);
      
  5. Logging Original IDs:

    • Issue: Obfuscated IDs in logs make debugging harder.
    • Fix: Log both original and encoded IDs during development:
      \Log::debug('Original ID', ['original' => $originalId, 'encoded' => $encodedId]);
      

Debugging Tips

  1. Validate Keys:

    • Verify primes/inverses using the spark command in a test environment:
      php artisan optimus:spark --verify
      
  2. Check for Middleware Conflicts:

    • If decoding fails, ensure middleware isn’t double-decoding IDs:
      // Debug middleware
      \Log::debug('Raw ID', [$request->route('id')]);
      \Log::debug('Decoded ID', [$this->optimus->decode($request->route('id'))]);
      
  3. Performance Bottlenecks:

    • Profile encoding/decoding in high-traffic routes:
      $start = microtime(true);
      $optimus->encode($id);
      $time = microtime(true) - $start;
      \Log::debug('Encoding time', [$time]);
      

Extension Points

  1. Custom Prime Generation:

    • Extend the spark command to generate tenant-specific primes:
      // app/Console/Commands/GenerateTenantPrimes.php
      use Jenssegers\Optimus\Optimus;
      
      class GenerateTenantPrimes extends Command
      {
          public function handle()
          {
              $tenants = Tenant::all();
              foreach ($tenants as $tenant) {
                  $prime = $this->generatePrimeForTenant($tenant->id);
                  Tenant::where('id', $tenant->id)->update(['optimus_prime' => $prime]);
              }
          }
      
          protected function generatePrimeForTenant(int $tenantId): int
          {
              // Custom logic to generate tenant-specific primes
              return 1580030173 + $tenantId; // Example
          }
      }
      
  2. Fallback for Invalid IDs:

    • Handle decoding failures gracefully:
      try {
          $id = $optimus->decode($request->id);
      } catch (\InvalidArgumentException $e) {
          \Log::warning('Invalid obfuscated ID', ['id' => $request->id]);
          return response()->json(['error' => 'Invalid ID'], 400);
      }
      
  3. Multi-Tenant Support:

    • Use a TenantOptimus facade to switch primes per tenant:
      // app/Facades/TenantOptimus.php
      use Illuminate\Support\Facades\Facade;
      
      class TenantOptimus extends Facade
      {
          protected static function getFacadeAccessor()
          {
              return 'tenant.optimus';
          }
      }
      
    • Bind dynamically in the OptimusServiceProvider:
      $this->app->bind('tenant.optimus', function ($app) {
          $tenant
      
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
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