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

Eloquent Uuid Laravel Package

juniorb2ss/eloquent-uuid

Eloquent UUID adds UUID support to Laravel's Eloquent models, letting you use universally unique identifiers as primary keys with minimal configuration. Useful for distributed apps or anywhere non-sequential IDs are preferred.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a single-purpose trait package, not a framework extension — there is nothing to publish, no config file, and likely no service provider to register. Before wiring it in, open the repo's src/ directory and composer.json: you need the exact trait namespace and the illuminate/database version constraint, because a package this small and this old (3 stars, 0 dependents) will often pin ^5.x and refuse to install on modern Laravel.

  1. Install and immediately check what you got:
composer require juniorb2ss/eloquent-uuid
composer show juniorb2ss/eloquent-uuid   # confirm version + illuminate constraint
  1. Add the trait to a model and tell Eloquent the key is not an integer — the trait only generates the value, it does not reconfigure the model:
use Juniorb2ss\EloquentUuid\UuidTrait; // verify actual name in src/

class Post extends Model
{
    use UuidTrait;

    public $incrementing = false;
    protected $keyType   = 'string';
}
  1. Create the column as a UUID, not an auto-increment:
Schema::create('posts', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->string('title');
    $table->timestamps();
});
  1. First use case to prove it works end-to-end: Post::create(['title' => 'hello']) in php artisan tinker, then dump $post->id and confirm it is a 36-character string that also exists in the database. If you get 0, your $incrementing/$keyType settings or the migration column type are wrong — the trait succeeded but Eloquent clobbered the value on read.

Implementation Patterns

Primary key replacement. The canonical pattern above: trait + $incrementing = false + $keyType = 'string' + uuid column. Keep the key name id so relationships, route binding, and find() behave normally. Do not add id to $fillable.

Secondary UUID column. If the trait writes to a fixed attribute (many of these packages hardcode the primary key, others accept a property), you can keep an integer PK for joins and expose a UUID externally. Only do this if the source actually supports a configurable attribute — otherwise write your own creating hook, which is five lines and easier to reason about:

protected static function booted()
{
    static::creating(fn ($m) => $m->uuid ??= (string) Str::uuid());
}

Relationships and foreign keys. Child tables must use $table->uuid('post_id') and $table->foreign('post_id')->references('id')->on('posts'). A mismatched unsignedBigInteger FK is the most common silent failure here — inserts succeed, joins return nothing. Define belongsTo/hasMany exactly as normal; no override needed when the UUID is the primary key.

Route model binding. With a UUID primary key, Route::get('/posts/{post}', ...) works untouched, because implicit binding uses getRouteKey(). With a secondary UUID column, override getRouteKeyName() to return 'uuid' and ensure the column is uniquely indexed.

Factories and seeders. Never set the key manually in a factory definition — omit id entirely and let the trait fire on creating. If you need deterministic IDs in tests, set the attribute explicitly before save() only after confirming the trait guards against overwriting; if it does not guard, either extend the trait locally or bypass it:

$post = new Post(['title' => 'x']);
$post->id = '00000000-0000-4000-8000-000000000000';
$post->save();

Bulk inserts. Model::insert() skips model events entirely — the trait will not fire. Use create()/save() in loops, or generate UUIDs yourself with Str::uuid() before calling insert().

Layering with other boot traits. Trait boot methods (boot{TraitName}) run in the order traits are declared on the class. If another trait's creating listener reads $model->getKey(), place UuidTrait first so the key exists when that listener fires.

Gotchas and Tips

  • Forgetting $keyType = 'string' is the number-one bug. MySQL returns 'a1b2...', Eloquent casts it to int, you get 0. Symptoms: find() returns null for an object you just saved, save() on an existing model inserts a duplicate.
  • Column type drift. $table->uuid() is char(36) on MySQL, uuid on Postgres, varchar on SQLite. Some UUID packages store binary(16) instead — mixing the two produces unreadable keys and broken comparisons. Match the migration to whatever the package generates.
  • UUIDv4 is not sortable. If you page through large tables by id, expect index fragmentation and arbitrary ordering. Use created_at for chronological queries, or prefer Laravel's HasUuids / Str::orderedUuid() if you control the codebase.
  • Check the package's last commit and Laravel constraint before betting on it. With 3 stars and 0 dependents, there is effectively no maintenance surface and no community answer if something breaks. Laravel 9+ ships Illuminate\Database\Eloquent\Concerns\HasUuids and HasUniqueStringIds natively — for any new project, use those instead; this package is only defensible in a legacy codebase where it is already in use.
  • Debugging checklist when a UUID model misbehaves: $model->getKeyName(), $model->getKeyType(), $model->getIncrementing(), Schema::getColumnType('posts', 'id'), and DB::listen(...) to see the actual INSERT payload.
  • Extension point: the cleanest way to customize generation is not to fork the trait but to add your own creating listener in booted() that overwrites the key after the trait runs — that gives you ordered UUIDs, prefixed IDs, or test doubles without touching vendor code.
  • Uniqueness collisions are astronomically unlikely with v4, but a duplicate-key exception on insert means your generator is not what you think it is (e.g. a truncated column, or a str_random fallback). Wrap batch imports in a retry or pre-generate keys.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo