Weave 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

Uuid Laravel Package

alt-three/uuid

Alt Three UUID is a lightweight Laravel integration for generating UUIDs, giving applications a simple way to create unique identifiers through the framework’s service container. It helps add reliable UUID support to models, services, and other PHP code with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

alt-three/uuid is a small, single-purpose converter: it takes a standard 128-bit UUID string and turns it into a numeric representation, and back again. It is the kind of package you reach for when a legacy system, an external API, or a reporting warehouse wants an integer key, but your Laravel application is built around UUID primary keys.

Install it (respecting the archive warning below):

composer require alt-three/uuid

There is no service provider, no config file, and no facade. Everything is a static/instantiable class under the AltThree\Uuid namespace. Open src/ first — the whole library is one or two files:

  • src/Uuid.php (or similarly named converter class) contains the actual toInteger() / toUuid() (or toInt() / toString()) methods.
  • composer.json tells you the PHP constraint and whether it relies on ext-bcmath, ext-gmp, or a pure-PHP big-number helper. Read this before installing — on a stock PHP build without bcmath/gmp you will get fatal errors or silently wrong results.
  • tests/ is the best documentation of edge cases (uppercase input, UUIDs starting with zero, v1 vs v4 inputs).

Your first use case is almost always one of these two:

use AltThree\Uuid\Uuid;

// Expose a numeric ID alongside your UUID primary key for an external consumer
$numeric = Uuid::toInteger('f47ac10b-58cc-4372-a567-0e02b2c3d479');

// Resolve an inbound numeric reference back to the UUID your app understands
$uuid = Uuid::toUuid($numeric);

Because a UUID is 128 bits and a PHP int is 64 bits, verify immediately what you get back. Run one round-trip in php artisan tinker and check gettype() of the result. If it is a numeric string, plan your schema and casts accordingly rather than fighting it later.

Implementation Patterns

Eloquent accessor, not a column change

The lowest-friction integration is to leave your UUID primary key untouched and derive the numeric form on read:

use AltThree\Uuid\Uuid;

class Order extends Model
{
    protected $primaryKey = 'id';
    protected $keyType = 'string';
    public $incrementing = false;

    public function getNumericIdAttribute(): string
    {
        return Uuid::toInteger($this->id);
    }
}

Then include it in API resources where a downstream system needs it:

return [
    'id'         => $this->id,
    'numeric_id' => $this->numeric_id,
    'status'     => $this->status,
];

Reverse lookup without a second index

If you need to accept the numeric form in a route, convert on the way in and delegate to normal route-model binding:

Route::get('/orders/{order}', function (string $order) {
    $uuid = Uuid::toUuid($order);

    return Order::findOrFail($uuid);
});

Add ->where('order', '[0-9]+') on the route so the two identifier shapes do not collide with any other slug-style routes.

Custom cast for round-tripping

If the numeric form appears in many places, wrap it once so controllers never touch the library:

namespace App\Casts;

use AltThree\Uuid\Uuid;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class NumericUuid implements CastsAttributes
{
    public function get($model, $key, $value, $attributes)
    {
        return Uuid::toUuid($value);
    }

    public function set($model, $key, $value, $attributes)
    {
        return Uuid::toInteger($value);
    }
}

Apply it only to a dedicated column (e.g. numeric_ref), not to your primary key — the cast flips the value on every read and write, which will confuse find() and relationship resolution.

Persisted mapping table for hot paths

Conversion is cheap but not free, and a numeric-string column sorts awkwardly and indexes differently across engines. When you need to query by numeric ID frequently, materialise the map:

Schema::create('uuid_map', function (Blueprint $table) {
    $table->string('numeric')->primary();
    $table->uuid('uuid')->unique();
    $table->index('uuid');
});

Populate it in the same transaction as the parent record (or via an observer on created), then join or look up against it. This keeps the big-number type concerns in a single, boring table instead of leaking into your domain schema.

Validation and normalisation at the boundary

Always validate the shape before conversion; the converter assumes a canonical UUID string.

$request->validate([
    'uuid' => ['required', 'uuid'],
]);

Normalise case (strtolower) and strip braces before handing the value over — most converters in this style operate on a strict 36-character canonical form, and a mismatch produces either an exception or a nonsense number.

Gotchas and Tips

The archive is the first gotcha. Last release was March 2018, it has 12 stars and zero dependents. Treat it as vendored code: pin an exact version in composer.json, add a test that round-trips a representative UUID, and put a note in your upgrade plan to inline the ~50 lines into app/Support/ when you next touch PHP versions. That is genuinely the cheaper long-term move for a library this small.

128 bits does not fit in a PHP int. Whatever the method is named, the return value for arbitrary UUIDs cannot be a native integer on 64-bit PHP. Expect a numeric string (bcmath/gmp backed) and never type-hint int on either end. If you get an int back, the package is truncating or discarding version/variant bits — check tests/ to confirm exactly which, because that is lossy and you cannot use it as a bijective key.

Extension dependency. Pure-PHP big-number math is slow; bcmath/gmp is fast but must be present in every environment including CI and your queue workers. Add ext-bcmath (or ext-gmp) to your composer.json require block so deploys fail loudly rather than at the first conversion in production.

Zero-padding and case. Converting back from a numeric representation must reproduce a 36-character canonical string. A UUID whose first hex group starts with zero will come back short if padding is wrong; uppercase input may produce a different numeric value than lowercase in byte-order-sensitive implementations. Normalise on input, assert the length on output.

Not a sorting key. If you are tempted to use the numeric form for ordering or cursor pagination, remember it is a 128-bit number encoded as a string — lexical comparison of variable-length numeric strings is wrong, and numeric comparison sorts by UUID randomness, not insertion order. Keep created_at or a bigIncrements sequence for ordering.

Exception surface is minimal. A malformed string typically throws a plain InvalidArgumentException or an ErrorException from the underlying math library, not a Laravel-friendly exception. Wrap conversions you do not control (anything derived from user input) in a small helper that throws a ValidationException or returns null, so you never leak a stack trace from a route.

Test the round trip, not the output. Do not assert on a hardcoded magic number in your test suite — you do not want your tests coupled to a big-number implementation detail you may replace. Assert Uuid::toUuid(Uuid::toInteger($uuid)) === $uuid across a set of fixtures including an all-zero UUID, an all-f UUID, and a v1 and v4 UUID. Those fixtures become your regression suite when you fork the code into the app.

Extension point is the seam, not the class. There is no interface to bind or config to publish, so if you need to swap implementations later, introduce your own App\Contracts\UuidConverter interface in the container, bind a thin adapter to this package today, and swap the binding for an in-house implementation tomorrow. Controllers depend on your interface, and the archived dependency stays confined to one file.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle