eve/uuid
eve/uuid is a lightweight Laravel package for UUID primary keys. It helps generate RFC-compliant UUIDs, assign them to Eloquent models, and use UUIDs in routes and database columns with minimal configuration. Simple setup and sensible defaults make UUID support easy to add.
The package is intentionally small: install it and you immediately get an Eve-namespaced UUID type that extends Ramsey's Ramsey\Uuid\Uuid.
composer require eve/uuid
There is no service provider, no config file, and no migrations to publish. The entire surface area is the Eve\Uuid\Uuid class in src/. Open that one file first — it tells you everything the package actually does (it is a subclass plus, potentially, a couple of convenience factories).
First use case, generate an ID:
use Eve\Uuid\Uuid;
$id = Uuid::uuid4();
(string) $id; // '9f8c8b7e-...'
$id->toString(); // same
Because it extends Ramsey's class, every static factory (uuid1(), uuid4(), fromString(), isValid(), NIL) and every instance method (getBytes(), equals(), compareTo()) that you already know from ramsey/uuid works unchanged. The value proposition is type identity — you can type-hint Eve\Uuid\Uuid and know you are in the Eveio ecosystem, not passing a raw string around.
Look next at whichever Eveio package pulled this in (e.g. eve/api) to see how IDs are actually shaped there; that is the real documentation.
Typed properties and DTOs. The main day-to-day use is replacing stringly-typed UUIDs with the class so static analysis and IDE completion work:
final class Character
{
public function __construct(
public readonly Uuid $id,
public readonly string $name,
) {}
}
$c = new Character(Uuid::uuid4(), 'Khan');
Eloquent model IDs. If you are already hydrating from the database, cast on the way in and construct on the way out:
protected $casts = [
'id' => 'string', // keep the column as char(36)
];
public static function booted(): void
{
static::creating(fn ($m) => $m->id ??= (string) Uuid::uuid4());
}
public function getIdAttribute($value): Uuid
{
return Uuid::fromString($value);
}
Prefer storing CHAR(36) (or BINARY(16) via getBytes() if you care about index size) and converting at the boundary rather than relying on a package-specific cast — this package does not ship one.
Validation at the edges. Use Uuid::isValid($input) before fromString(); fromString() throws InvalidUuidStringException on malformed input, which is easy to forget in request validators:
if (! Uuid::isValid($request->input('id'))) {
abort(422);
}
Cross-package boundaries. When passing IDs into Eveio services or serializing to JSON, cast to string at the last moment ((string) $uuid). Ramsey's object is not JsonSerializable by default, so sending the object directly to json_encode yields {}.
Ordering and equality. Use $a->equals($b) rather than === — two UUID instances for the same value are different objects, and this is the most common bug when wiring up lookups.
ramsey/uuid directly, because the wrapper adds almost nothing you cannot reproduce in one class.ramsey/uuid. Because Eve\Uuid\Uuid extends a Ramsey class, a major bump in ramsey/uuid (v3 → v4 changed constructor signatures and removed some static helpers) can silently break this package. Check composer why-not ramsey/uuid before upgrading the underlying library.Uuid in $casts, Rule::uuid(), or a Blade helper, write them yourself.UuidInterface (Ramsey's), it will accept the Eve wrapper, but not vice versa in strict type declarations. Pick one and be consistent per layer — typically the Eve type in your domain, Ramsey's interface in generic libraries.var_dump() and dd() on the object show Ramsey internals; use ->toString() in logs. When UUIDs "disappear" from JSON payloads or cache keys, it is almost always an un-cast object being stringified implicitly.Eve\Uuid\Uuid yourself (e.g. OrderId extends Uuid) for domain-specific ID types. If you find yourself wanting factories, casts, or validation rules, that is a signal to keep ramsey/uuid and wrap it in your own value objects instead.How can I help you explore Laravel packages today?