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 Model Nanoid Laravel Package

parables/laravel-model-nanoid

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Run composer require parables/laravel-model-nanoid in your Laravel project.
  2. Publish Config: Execute php artisan vendor:publish --provider="Parables\LaravelModelNanoid\LaravelModelNanoidServiceProvider" to publish the config file.
  3. Model Setup: Add the HasNanoId trait to your Eloquent model:
    use Parables\LaravelModelNanoid\HasNanoId;
    
    class User extends Model
    {
        use HasNanoId;
    }
    
  4. Migration: Add a nano_id column to your table (e.g., string with length 21 or more):
    Schema::table('users', function (Blueprint $table) {
        $table->string('nano_id')->unique()->after('id');
    });
    
  5. First Use: Create a model instance—it will automatically generate a NanoID:
    $user = User::create(['name' => 'John Doe']);
    // $user->nano_id will be a 21-character string like "V1StGXW8_G5d0J9KqP2x"
    

Where to Look First

  • Config File: config/nanoid.php for customizing alphabet, size, or randomness.
  • Trait Methods: HasNanoId provides getNanoId(), setNanoId(), and generateNanoId() for manual control.
  • Testing: Run php artisan nanoid:test to verify NanoID generation.

Implementation Patterns

Core Workflows

  1. Automatic Generation:

    • NanoIDs are auto-generated on create() if the field is empty. No manual intervention needed.
    • Example:
      $post = Post::create(['title' => 'Hello World']); // nano_id auto-populated
      
  2. Manual Overrides:

    • Generate a NanoID manually for edge cases (e.g., bulk inserts):
      $nanoId = $model->generateNanoId();
      $model->setNanoId($nanoId);
      $model->save();
      
  3. Querying by NanoID:

    • Use where('nano_id', $value) for lookups. Ensure the column is indexed for performance:
      $user = User::where('nano_id', 'V1StGXW8_G5d0J9KqP2x')->first();
      
  4. Custom Alphabets:

    • Override the default alphabet (e.g., for URL-friendly slugs) in config/nanoid.php:
      'alphabet' => '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghjkmnpqrstuvwxyz',
      
  5. Integration with APIs:

    • Use NanoIDs in API responses or URLs (e.g., /users/{nano_id}). Example:
      Route::get('/users/{nano_id}', [UserController::class, 'show']);
      
  6. Seeding:

    • Seed NanoIDs in factories or seeders:
      User::factory()->create(['nano_id' => \Str::random(21)]); // Not recommended; use trait instead
      
    • Better: Let the trait handle generation:
      User::factory()->create(); // Auto-generates nano_id
      

Advanced Patterns

  1. Composite Keys:

    • Combine id (auto-increment) and nano_id for hybrid lookups:
      $model = Model::where('id', $id)->orWhere('nano_id', $nano_id)->first();
      
  2. Soft Deletes:

    • NanoIDs work seamlessly with SoftDeletes. Ensure the deleted_at column is indexed separately.
  3. Caching:

    • Cache NanoID-based queries (e.g., Cache::remember()) to avoid repeated DB lookups.
  4. Events:

    • Listen for creating events to customize NanoID generation:
      User::creating(function ($user) {
          if (empty($user->nano_id)) {
              $user->nano_id = $user->generateNanoId(16); // Shorter ID for testing
          }
      });
      
  5. Testing:

    • Mock NanoID generation in tests:
      $model = new User();
      $model->shouldReceive('generateNanoId')->andReturn('TEST123');
      

Gotchas and Tips

Pitfalls

  1. Database Indexing:

    • Gotcha: Forgetting to index the nano_id column will cause slow queries.
    • Fix: Add an index in migrations:
      $table->string('nano_id')->unique();
      $table->index('nano_id'); // Explicit index (optional but recommended)
      
  2. Collision Risk:

    • Gotcha: NanoIDs are extremely unlikely to collide (probability: ~1 in 10^21 for 21 chars), but custom alphabets or short sizes (e.g., 10 chars) increase risk.
    • Fix: Use the default 21-character size or increase it if needed.
  3. Auto-Increment Conflicts:

    • Gotcha: If you disable auto-increment ($table->id()->unsigned(false)), the package won’t work as expected.
    • Fix: Keep auto-increment enabled for the primary key (id). NanoIDs are for secondary use cases.
  4. Case Sensitivity:

    • Gotcha: The default alphabet includes uppercase letters, but some databases (e.g., MySQL with utf8mb4_bin collation) treat case-insensitively.
    • Fix: Use a case-insensitive collation or stick to lowercase in the alphabet.
  5. Migration Order:

    • Gotcha: Adding nano_id to an existing table without a default value may cause issues if the column is required.
    • Fix: Use nullable() during migration and backfill later:
      $table->string('nano_id')->nullable()->unique();
      // Later: update existing records with NanoIDs
      
  6. Performance:

    • Gotcha: NanoIDs are longer than UUIDs (21 vs. 36 chars) but faster to generate. However, indexing them adds overhead.
    • Tip: Use NanoIDs for public-facing IDs (URLs, APIs) and keep id for internal joins.

Debugging Tips

  1. Validation Errors:

    • If NanoIDs fail validation (e.g., wrong length), check:
      • The size in config/nanoid.php matches your column length.
      • The alphabet hasn’t been truncated unexpectedly.
  2. Duplicate NanoIDs:

    • Debug: Run php artisan nanoid:test to verify generation uniqueness.
    • Cause: Likely a custom randomness source or alphabet issue.
  3. Slow Queries:

    • Debug: Use EXPLAIN in MySQL or pg_explain in PostgreSQL to check if the nano_id index is being used.
    • Fix: Ensure the query uses where('nano_id', ...) and not like or partial matches.
  4. Config Overrides:

    • Tip: Clear the config cache after changes:
      php artisan config:clear
      

Extension Points

  1. Custom Randomness:

    • Override the random bytes generator in config/nanoid.php:
      'random_bytes_generator' => function () {
          return random_bytes(10); // Custom logic
      },
      
  2. Dynamic NanoID Length:

    • Generate NanoIDs of varying lengths per model:
      $model->generateNanoId(16); // 16-character ID
      
  3. Event Hooks:

    • Extend the trait to add pre/post hooks:
      use Parables\LaravelModelNanoid\HasNanoId;
      
      class User extends Model
      {
          use HasNanoId;
      
          protected static function bootHasNanoId()
          {
              static::creating(function ($model) {
                  logger()->info("Generating NanoID for {$model->class}");
              });
          }
      }
      
  4. Database-Specific Optimizations:

    • For PostgreSQL, use citext for case-insensitive NanoIDs:
      $table->string('nano_id')->unique();
      $table->engine = 'citext'; // PostgreSQL-specific
      
  5. Fallback for Missing IDs:

    • Handle cases where nano_id is missing in existing records:
      if (empty($model->nano_id)) {
          $model->nano_id = $model->generateNanoId();
      }
      
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.
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
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope