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

Laravel Uuidable Laravel Package

labrodev/laravel-uuidable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require labrodev/uuidable
    

    Ensure your project meets the PHP 8.1+ requirement.

  2. Add UUID Column: Add a uuid column to your migration (or existing table) using:

    $table->uuid('uuid')->unique()->nullable()->default(DB::raw('(uuid_generate_v4()))'));
    

    (Note: The default clause is optional if the trait handles generation.)

  3. Apply Trait: Use the trait in your Eloquent model:

    use Labrodev\Uuidable\ModelHasUuid;
    
    class User extends Model
    {
        use ModelHasUuid;
    }
    
  4. First Use Case: Create a model instance—it will auto-generate a UUID:

    $user = User::create(['name' => 'John Doe']);
    echo $user->uuid; // e.g., "123e4567-e89b-12d3-a456-426614174000"
    

Where to Look First

  • Trait Documentation: Focus on ModelHasUuid and its methods (e.g., fetchUuidColumn()).
  • Migration Example: Check the GitHub repo for edge cases (e.g., UUID generation strategies).
  • Testing: Run php artisan test in the package directory to understand behavior (e.g., UUID uniqueness, fallback logic).

Implementation Patterns

Core Workflows

  1. Auto-Generation:

    • The trait hooks into boot() to ensure UUIDs are generated on creating events.
    • Pattern: Use creating(Model $model) in your model to validate UUIDs before saving:
      protected static function bootModelHasUuid()
      {
          static::creating(function ($model) {
              if (empty($model->{$model->fetchUuidColumn()})) {
                  $model->{$model->fetchUuidColumn()} = Str::uuid();
              }
          });
      }
      
  2. Custom Column Names:

    • Override fetchUuidColumn() for non-standard column names (e.g., custom_id):
      protected function fetchUuidColumn(): string
      {
          return 'custom_id';
      }
      
    • Pattern: Use this when integrating with legacy databases or APIs requiring specific field names.
  3. UUID as Primary Key:

    • Replace id with uuid as the primary key in migrations:
      $table->uuid('uuid')->primary();
      
    • Pattern: Update getKeyName() in your model:
      public function getKeyName()
      {
          return 'uuid';
      }
      
  4. API Responses:

    • Normalize UUID formatting in API responses (e.g., hyphenated vs. non-hyphenated):
      protected $appends = ['uuid'];
      protected $casts = ['uuid' => 'string'];
      
      public function getUuidAttribute($value)
      {
          return Str::of($value)->replace('{5}', '-')->replace('{9}', '-');
      }
      

Integration Tips

  • Seeding: Use Str::uuid() in seeders to generate deterministic UUIDs:
    $user = User::create(['name' => 'Admin', 'uuid' => Str::uuid()]);
    
  • Relationships: Ensure foreign keys in related models use UUIDs:
    $table->uuid('user_id')->foreign()->constrained('users');
    
  • Testing: Mock UUID generation in tests:
    $this->partialMock(User::class, function ($mock) {
        $mock->shouldReceive('fetchUuidColumn')->andReturn('uuid');
    });
    

Gotchas and Tips

Pitfalls

  1. UUID Generation Race Conditions:

    • If using default(DB::raw('uuid_generate_v4()')) in migrations, ensure the database supports it (PostgreSQL, MySQL 8+).
    • Fix: Let the trait handle generation in PHP for consistency across databases.
  2. Primary Key Conflicts:

    • If uuid is the primary key, ensure it’s marked as unique in migrations to avoid duplicates.
    • Debug: Check for SQLSTATE[23000] errors during create() operations.
  3. Trait Method Overrides:

    • Overriding fetchUuidColumn() must return a string. Non-string values (e.g., null) will cause runtime errors.
    • Tip: Validate the column exists in the database before overriding.
  4. UUID Length in Databases:

    • MySQL’s CHAR(36) may truncate UUIDs if not explicitly cast. Use BINARY(16) for binary UUIDs or VARCHAR(36) for strings.
    • Fix: Adjust your migration:
      $table->binary('uuid')->as('uuid')->unique();
      
  5. Laravel Scout Integration:

    • If using Scout, UUIDs may cause issues with where clauses. Use whereKey() instead:
      User::whereKey($uuid)->get();
      

Debugging

  • Missing UUIDs:

    • Verify the trait is loaded (check composer.json for Labrodev\Uuidable).
    • Ensure the creating event fires (add a dd() in the trait’s boot() method temporarily).
  • Performance:

    • UUID generation in PHP is slower than database-level generation. Benchmark for high-write workloads.

Extension Points

  1. Custom UUID Strategies:

    • Extend the trait to support version 1/3/5 UUIDs:
      use Ramsey\Uuid\Uuid;
      
      protected function generateUuid(): string
      {
          return Uuid::uuid5(Uuid::NAMESPACE_DNS, 'example.com')->toString();
      }
      
  2. UUID Validation:

    • Add validation rules in rules():
      public function rules()
      {
          return [
              'uuid' => 'required|uuid',
          ];
      }
      
  3. UUID Display:

    • Create an accessor for shortened UUIDs (e.g., first 8 chars):
      public function getShortUuidAttribute()
      {
          return Str::limit($this->uuid, 8);
      }
      
  4. Fallback for Non-UUID Databases:

    • Use a hybrid approach (UUID in PHP + integer ID in DB):
      protected function fetchUuidColumn(): string
      {
          return 'uuid';
      }
      
      protected static function bootModelHasUuid()
      {
          static::created(function ($model) {
              if (empty($model->uuid)) {
                  $model->uuid = Str::uuid();
                  $model->save();
              }
          });
      }
      
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours