Laravel UUID v6.2.0
Eloquent Models Integration
webpatser@dev:
~/laravel-uuid/6.2.0
$ cat eloquent-models.md
Eloquent Models - Laravel UUID v6.2.0
Seamlessly integrate UUIDs into your Laravel Eloquent models with automatic generation, casting, and high-performance alternatives to Laravel's built-in UUID features.
High-Performance HasUuids Trait
Drop-in replacement for Laravel's HasUuids
trait with 15% better performance:
use Illuminate\Database\Eloquent\Model;use Webpatser\LaravelUuid\HasUuids; // Instead of Laravel's trait class User extends Model{ use HasUuids; // Uses our high-performance library protected $fillable = ['name', 'email'];} // Usage - same API as Laravel's traitecho $user->id; // Auto-generated UUID: "550e8400-e29b-41d4-a716-446655440000"
Migration Setup
Set up your database tables with UUID primary keys:
use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; return new class extends Migration{ public function up() { Schema::create('users', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('name'); $table->string('email')->unique(); $table->uuid('parent_id')->nullable(); $table->timestamps(); // Foreign key to another UUID $table->foreign('parent_id')->references('id')->on('users'); }); }};
Customizing UUID Generation
Control which UUID version is used and customize the generation logic:
use Illuminate\Database\Eloquent\Model;use Webpatser\LaravelUuid\HasUuids;use Webpatser\Uuid\Uuid; class User extends Model{ use HasUuids; // Customize UUID generation method public function newUniqueId(): string { return (string) Uuid::v7(); // Use V7 for better database performance // Or: return (string) Uuid::v4(); // Standard random UUIDs // Or: return (string) Uuid::generate(1); // Time-based V1 } // Specify which columns get UUIDs (optional) public function uniqueIds(): array { return ['id', 'uuid', 'external_id']; }} // Additional trait methods available$user = User::create(['name' => 'John']);echo $user->getUuidVersion(); // "7" (or whichever version you're using)$isOrdered = $user->usesOrderedUuids(); // true for V7 UUIDs$timestamp = $user->getUuidTimestamp(); // Extract timestamp (V1/V7 only)
UUID Casting
Automatically convert UUID strings to UUID objects in your models:
use Illuminate\Database\Eloquent\Model;use Webpatser\LaravelUuid\UuidCast; class User extends Model{ protected $casts = [ 'id' => UuidCast::class, 'parent_id' => UuidCast::class, 'session_uuid' => UuidCast::class, ];} // Usage - automatic conversion$user = User::find('550e8400-e29b-41d4-a716-446655440000');$userId = $user->id; // Returns Webpatser\Uuid\Uuid instance // Access UUID propertiesecho $userId->string; // "550e8400-e29b-41d4-a716-446655440000"echo $userId->hex; // "550e8400e29b41d4a716446655440000"echo $userId->version; // 4echo $userId->variant; // "RFC 4122" // When saving, UUID objects are automatically converted to strings$user->parent_id = Uuid::v7();$user->save(); // Stores as string in database
Model Relationships with UUIDs
UUIDs work seamlessly with Eloquent relationships:
class User extends Model{ use HasUuids; protected $fillable = ['name', 'email']; // One-to-many relationship public function posts() { return $this->hasMany(Post::class); } // Many-to-many with pivot UUIDs public function roles() { return $this->belongsToMany(Role::class) ->using(UserRole::class) // Pivot model with UUIDs ->withTimestamps(); }} class Post extends Model{ use HasUuids; protected $fillable = ['title', 'content']; public function user() { return $this->belongsTo(User::class); }} // Pivot model with UUIDsclass UserRole extends Pivot{ use HasUuids; protected $table = 'user_roles';} // Usage works exactly like integer keys$post = $user->posts()->create(['title' => 'Hello World', 'content' => '...']);echo $post->user->name; // "John"
Migration for Relationships
// Posts table migrationSchema::create('posts', function (Blueprint $table) { $table->uuid('id')->primary(); $table->uuid('user_id'); // Foreign key $table->string('title'); $table->text('content'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); $table->index('user_id'); // Index for performance}); // Many-to-many pivot tableSchema::create('user_roles', function (Blueprint $table) { $table->uuid('id')->primary(); $table->uuid('user_id'); $table->uuid('role_id'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); $table->foreign('role_id')->references('id')->on('roles'); $table->unique(['user_id', 'role_id']);});
Route Model Binding
UUIDs work seamlessly with Laravel's route model binding:
// routes/web.phpRoute::get('/user/{user}', [UserController::class, 'show']);Route::get('/user/{user}/post/{post}', [PostController::class, 'show']); // UserController.phpclass UserController extends Controller{ public function show(User $user) { // Laravel automatically finds the user by UUID return view('user.show', compact('user')); }} // URLs work with UUIDs:// /user/550e8400-e29b-41d4-a716-446655440000// /user/550e8400-e29b-41d4-a716-446655440000/post/018f4e7c-8b3a-7000-8000-123456789abc
Custom Route Key Names
class User extends Model{ use HasUuids; // Use a different column for route model binding public function getRouteKeyName() { return 'uuid'; // Instead of 'id' }} // Or specify in your routesRoute::get('/user/{user:uuid}', [UserController::class, 'show']);
Performance Considerations
🚀
Performance Tips
- • Use V7 UUIDs (
Uuid::v7()
) for better database clustering - • Our
HasUuids
trait is 15% faster than Laravel's - • Index UUID foreign keys for optimal query performance
- • Consider binary storage for 55% space savings (see Binary Storage docs)
// For maximum database performanceclass User extends Model{ use HasUuids; public function newUniqueId(): string { // V7 UUIDs sort chronologically - better for database clustering return (string) Uuid::v7(); }} // Migration with proper indexingSchema::create('users', function (Blueprint $table) { $table->uuid('id')->primary(); $table->uuid('parent_id')->nullable(); $table->string('email')->unique(); $table->timestamps(); // Index foreign key columns $table->index('parent_id'); // Composite indexes for common queries $table->index(['parent_id', 'created_at']);});
Advanced Model Patterns
Base Model with UUID
// Base model for all your UUID modelsabstract class BaseUuidModel extends Model{ use HasUuids; public function newUniqueId(): string { return (string) Uuid::v7(); // Consistent across all models }} // Use in your modelsclass User extends BaseUuidModel{ protected $fillable = ['name', 'email'];} class Post extends BaseUuidModel{ protected $fillable = ['title', 'content', 'user_id'];}
Soft Deletes with UUIDs
use Illuminate\Database\Eloquent\SoftDeletes; class User extends Model{ use HasUuids, SoftDeletes; protected $fillable = ['name', 'email']; protected $dates = ['deleted_at'];} // MigrationSchema::create('users', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('name'); $table->string('email'); $table->timestamps(); $table->softDeletes(); // Adds deleted_at timestamp});
Testing with UUIDs
// In your testsuse Illuminate\Foundation\Testing\RefreshDatabase;use Tests\TestCase; class UserTest extends TestCase{ use RefreshDatabase; public function test_user_creation() { $user = User::create([ 'name' => 'Test User', ]); // Assert UUID was generated $this->assertNotNull($user->id); $this->assertTrue(Str::isUuid($user->id)); // Test route model binding $response = $this->get("/user/{$user->id}"); $response->assertStatus(200); } public function test_uuid_relationships() { $user = User::factory()->create(); $post = Post::factory()->create(['user_id' => $user->id]); $this->assertEquals($user->id, $post->user_id); $this->assertEquals($user->name, $post->user->name); }}