pmcpimentel/laravel-nanoid

NanoID integration for Laravel — short, secure, URL-safe IDs with Eloquent trait, Facade, and schema macros.

v1.0.1 2025-10-01 23:22 UTC

This package is not auto-updated.

Last update: 2025-10-02 02:47:48 UTC


README

Laravel NanoID

A tiny, secure, URL-friendly, unique string ID generator for Laravel

Latest Version on Packagist Total Downloads License

Generate short, secure, URL-safe IDs perfect for use as primary keys, slugs, or any unique identifier in your Laravel application.

Features - Installation - Usage - Configuration - Contributing

Why NanoID?

  • Compact: Shorter than UUID (21 chars vs 36) with similar collision resistance
  • URL-Safe: Uses a safe alphabet (A-Za-z0-9_-) suitable for URLs
  • Secure: Uses cryptographically strong random API
  • Fast: Efficient generation with minimal overhead

Features

  • 🎯 Eloquent IntegrationHasNanoId trait for automatic model key generation
  • 🔧 Schema MacrosnanoId() and foreignNanoId() Blueprint methods
  • 🎨 String Macro – Generate IDs with Str::nanoid()
  • 🌍 Global Helper – Simple nanoid() function
  • Validation Rule – Validate NanoID format and constraints
  • ⚙️ Configurable – Customize length and alphabet per your needs
  • 🚀 Laravel Auto-Discovery – Zero configuration required

Installation

composer require pmcpimentel/laravel-nanoid

Publishing Configuration (Optional)

The package works out of the box with sensible defaults. To customize:

php artisan vendor:publish --provider="Pmcpimentel\\LaravelNanoId\\ServiceProvider" --tag=config

This creates config/nano_id.php where you can adjust default length and alphabet.

Usage

Quick Start

Generate a NanoID anywhere in your application:

use Illuminate\Support\Str;

$id = Str::nanoid();
// => "V1StGXR8_Z5jdHi6B-myT"

Or use the global helper:

$id = nanoid();
// => "4pZL6K2zH8fN3qR7wE9mT"

Advanced Generation

Customize length and alphabet:

// Shorter ID (10 characters)
$shortId = Str::nanoid(10);
// => "4pZL6K2zH8"

// Custom alphabet (numbers only)
$numericId = Str::nanoid(8, '0123456789');
// => "94852761"

// Custom alphabet with custom length
$customId = Str::nanoid(12, 'ABCDEF0123456789');
// => "3F7A9C2E1D0B"

Eloquent Models

Use the HasNanoId trait to automatically generate NanoID primary keys on model creation:

use Illuminate\Database\Eloquent\Model;
use Pmcpimentel\LaravelNanoId\Traits\HasNanoId;

class Order extends Model
{
    use HasNanoId;

    // That's it! The trait handles everything:
    // - Sets $incrementing = false
    // - Sets $keyType = 'string'
    // - Generates NanoID before creation
}

Now your models will automatically get a NanoID:

$order = Order::create(['status' => 'pending']);
echo $order->id;
// => "V1StGXR8_Z5jdHi6B-myT"

Migrations & Schema

Use the Blueprint macros for clean, expressive migrations:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

// Create table with NanoID primary key
Schema::create('orders', function (Blueprint $table) {
    $table->nanoId();
    $table->string('status');
    $table->decimal('amount', 10, 2);
    $table->timestamps();
});

// Add foreign key relationships
Schema::create('payments', function (Blueprint $table) {
    $table->nanoId();
    $table->foreignNanoId('order_id')->constrained('orders');
    $table->string('method');
    $table->timestamps();
});

// Add nullable foreign key
Schema::create('refunds', function (Blueprint $table) {
    $table->nanoId();
    $table->foreignNanoId('payment_id')->nullable()->constrained('payments');
    $table->timestamps();
});

The nanoId() macro creates a string column with the configured default length and sets it as primary key.

Validation

Validate that incoming IDs conform to NanoID format:

use Pmcpimentel\LaravelNanoId\Rules\NanoIdRule;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function show(Request $request)
    {
        $validated = $request->validate([
            'id' => ['required', new NanoIdRule()],
        ]);

        $order = Order::findOrFail($validated['id']);
        return response()->json($order);
    }
}

Custom validation constraints:

// Validate specific length
$request->validate([
    'id' => [new NanoIdRule(length: 12)],
]);

// Validate specific alphabet
$request->validate([
    'code' => [new NanoIdRule(alphabet: '0123456789ABCDEF')],
]);

// Validate both
$request->validate([
    'token' => [new NanoIdRule(length: 16, alphabet: 'ABCDEFGHIJKLMNOP')],
]);

Using the Facade

Access the generator directly via the facade:

use Pmcpimentel\LaravelNanoId\Facades\NanoId;

$id = NanoId::generate();
$customId = NanoId::generate(10, 'ABC123');

Configuration

After publishing the config file, you'll find config/nano_id.php with these defaults:

return [
    'length' => 21,
    'alphabet' => '_-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
];

Default Settings

  • Length: 21 characters (similar collision resistance to UUIDv4)
  • Alphabet: 64 URL-safe characters (A-Za-z0-9_-)

Collision Probability

Approximate collision rate when generating 1 million IDs with the default 64-character alphabet:

Length Approx. Odds Recommended For
8 ~1 in 560 Low-volume, non-critical
9 ~1 in 36k Development/Testing
10 ~1 in 2.3M Internal tools
11 ~1 in 150M Small to medium apps
12 ~1 in 9.4B Large production apps
13 ~1 in 600B Enterprise/High-volume
21 ~1 in 1.7e20 Default - UUID equivalent

💡 Tip: You can use NanoID Collision Calculator to calculate probabilities for your specific use case.

Custom Alphabets

You can customize the alphabet for specific use cases:

// Numbers only
'alphabet' => '0123456789'

// Uppercase letters and numbers
'alphabet' => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

// Lowercase alphanumeric
'alphabet' => '0123456789abcdefghijklmnopqrstuvwxyz'

// No ambiguous characters (no 0, O, I, l)
'alphabet' => '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

Requirements

  • PHP: 8.1 or higher
  • Laravel: 10.x, 11.x or 12.x

Testing & Development

Installation

composer install

Available Commands

composer test              # Run Pest test suite
composer analyse           # Run PHPStan static analysis
composer lint              # Run PHP-CS-Fixer (dry run)
composer lint-fix          # Run PHP-CS-Fixer and apply fixes

Running Tests

composer test

Code Quality

This package uses:

  • Pest for testing
  • PHPStan for static analysis (level max)
  • PHP-CS-Fixer for code style

Contributing

We welcome contributions! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and quality checks:
    composer test
    composer analyse
    composer lint-fix
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Contribution Guidelines

  • Write tests for new features
  • Follow PSR-12 coding standards
  • Update documentation for API changes
  • Keep backward compatibility when possible

By contributing, you agree to license your work under the MIT license.

Security

If you discover a security vulnerability, please email the maintainer directly rather than using the issue tracker. All security vulnerabilities will be promptly addressed.

Credits

License

The MIT License (MIT). Please see License File for more information.

⬆ back to top

Made with ❤️ for the Laravel community