pmcpimentel / laravel-nanoid
NanoID integration for Laravel — short, secure, URL-safe IDs with Eloquent trait, Facade, and schema macros.
Requires
- php: ^8.1
- hidehalo/nanoid-php: ^1.1
- laravel/framework: ^10.0|^11.0|^12.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^v3.0
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^v3.0
- phpstan/phpstan: ^2.0
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
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 Integration –
HasNanoId
trait for automatic model key generation - 🔧 Schema Macros –
nanoId()
andforeignNanoId()
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:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes
- Run tests and quality checks:
composer test composer analyse composer lint-fix
- Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - 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
- Author: pmcpimentel
- Built with: hidehalo/nanoid-php
- Inspired by: NanoID by Andrey Sitnik
License
The MIT License (MIT). Please see License File for more information.
Made with ❤️ for the Laravel community