A powerful Laravel package to generate unique, prefixed IDs with database transaction safety and race condition protection. Perfect for invoices, complaints, quotations, orders, and any document that needs professional numbering.
// Generate professional IDs instantly
$invoiceId = generateUniqueId('invoice', 'invoices', 'invoice_no');
// Output: INV-20250814-0001
$complaintId = generateUniqueId('complaint', 'complaints', 'complaint_no');
// Output: CMP-20250814-0001When building applications, you often need to generate unique document numbers like:
- Invoice Numbers:
INV-20250814-0001 - Complaint IDs:
CMP-20250814-0001 - Order Numbers:
ORD-20250814-0001
Common challenges:
- Race Conditions: Two users creating records simultaneously can get the same number
- Non-Professional Format: Simple auto-increment IDs look unprofessional
- No Business Logic: Hard to identify document type from the number
- Maintenance Overhead: Writing custom numbering logic for each model
This package provides:
- ✅ Race Condition Safe: Uses database transactions and row locking
- ✅ Professional Format:
PREFIX-YYYYMMDD-XXXXformat - ✅ Zero Conflicts: Guaranteed unique IDs across your entire application
- ✅ Laravel Native: Follows Laravel conventions and best practices
- ✅ Future Proof: Compatible with Laravel 11, 12, and beyond
- ✅ Auto-Scalable: Handles millions of records without performance issues
composer require alimarchal/id-generatorThat's it! Thanks to Laravel's auto-discovery, the package is immediately ready to use.
php artisan vendor:publish --tag=id-generator-migrations
php artisan migrateThis creates an id_prefixes table with sample data:
| id | name | prefix | created_at | updated_at |
|---|---|---|---|---|
| 1 | invoice | INV | ... | ... |
| 2 | complaint | CMP | ... | ... |
| 3 | quotation | QTN | ... | ... |
use Illuminate\Support\Facades\DB;
DB::table('id_prefixes')->insert([
['name' => 'order', 'prefix' => 'ORD'],
['name' => 'receipt', 'prefix' => 'RCP'],
['name' => 'estimate', 'prefix' => 'EST'],
]);The simplest way to generate IDs anywhere in your application.
// Generate invoice number using 'invoice' type from database
$invoiceId = generateUniqueId('invoice', 'invoices', 'invoice_no');
// Output: INV-20250814-0001
// Generate complaint number
$complaintId = generateUniqueId('complaint', 'complaints', 'complaint_no');
// Output: CMP-20250814-0001
// Generate quotation number
$quotationId = generateUniqueId('quotation', 'quotations', 'quotation_no');
// Output: QTN-20250814-0001// Generate ID with custom prefix (no database lookup)
$orderId = generateUniqueIdWithPrefix('ORD', 'orders', 'order_no');
// Output: ORD-20250814-0001
$customId = generateUniqueIdWithPrefix('CUST', 'customers', 'customer_id');
// Output: CUST-20250814-0001Perfect when you need more control or are following SOLID principles.
<?php
namespace App\Http\Controllers;
use Alimarchal\IdGenerator\IdGenerator;
use App\Models\Invoice;
use Illuminate\Http\Request;
class InvoiceController extends Controller
{
public function store(Request $request, IdGenerator $idGenerator)
{
// Method 1: Using database prefix
$invoiceNumber = $idGenerator->generate('invoice', 'invoices', 'invoice_no');
// Method 2: Using direct prefix
$orderNumber = $idGenerator->generateWithPrefix('ORD', 'orders', 'order_no');
$invoice = Invoice::create([
'invoice_no' => $invoiceNumber,
'customer_name' => $request->customer_name,
'amount' => $request->amount,
]);
return response()->json(['invoice' => $invoice], 201);
}
}class OrderController extends Controller
{
public function createOrder(Request $request, IdGenerator $idGenerator)
{
$orderNumber = $idGenerator->generate('order', 'orders', 'order_no');
// Output: ORD-20250814-0001
$invoiceNumber = $idGenerator->generate('invoice', 'invoices', 'invoice_no');
// Output: INV-20250814-0001
$trackingNumber = $idGenerator->generateWithPrefix('TRK', 'shipments', 'tracking_no');
// Output: TRK-20250814-0001
// Create order with all numbers...
}
}class TicketController extends Controller
{
public function createTicket(Request $request)
{
$ticketNumber = generateUniqueId('ticket', 'tickets', 'ticket_no');
// Output: TKT-20250814-0001
$ticket = Ticket::create([
'ticket_no' => $ticketNumber,
'title' => $request->title,
'priority' => $request->priority,
]);
return response()->json(['ticket' => $ticket], 201);
}
}<?php
namespace App\Http\Controllers;
use App\Models\Invoice;
use Illuminate\Http\Request;
class InvoiceController extends Controller
{
public function store(Request $request)
{
// Validate request...
$request->validate([
'customer_name' => 'required|string',
'amount' => 'required|numeric',
]);
// Generate unique invoice number
$invoiceNumber = generateUniqueId('invoice', 'invoices', 'invoice_no');
// Create invoice
$invoice = Invoice::create([
'invoice_no' => $invoiceNumber,
'customer_name' => $request->customer_name,
'amount' => $request->amount,
'created_at' => now(),
]);
return response()->json([
'message' => 'Invoice created successfully!',
'invoice' => $invoice
], 201);
}
}- Millions of Records: Tested with millions of records without performance degradation
- High Concurrency: Can handle hundreds of simultaneous requests without conflicts
- Database Optimized: Uses efficient queries with proper indexing
- Memory Efficient: Minimal memory footprint
// This package handles this scenario automatically:
// User A and User B create invoices at the EXACT same millisecond
// Without protection:
// User A gets: INV-20250814-0001
// User B gets: INV-20250814-0001 ❌ (DUPLICATE!)
// With this package:
// User A gets: INV-20250814-0001 ✅
// User B gets: INV-20250814-0002 ✅ (UNIQUE!)This package is designed to work with current and future Laravel versions:
- ✅ Laravel 11 - Fully supported
- ✅ Laravel 12 - Ready for future releases
- ✅ PHP 8.2+ - Modern PHP support
- Semantic Versioning: We follow SemVer for predictable updates
- Laravel Compatibility: New Laravel versions are supported within 30 days of release
- Backward Compatibility: Minor updates never break existing functionality
// Different prefixes for different environments
// In your AppServiceProvider boot method:
if (app()->environment('production')) {
DB::table('id_prefixes')->updateOrInsert(
['name' => 'invoice'],
['prefix' => 'INV']
);
} else {
DB::table('id_prefixes')->updateOrInsert(
['name' => 'invoice'],
['prefix' => 'TEST-INV']
);
}// Add new prefix types dynamically
DB::table('id_prefixes')->insert([
'name' => 'purchase-order',
'prefix' => 'PO',
'created_at' => now(),
'updated_at' => now()
]);
// Use the new prefix
$poNumber = generateUniqueId('purchase-order', 'purchase_orders', 'po_number');
// Output: PO-20250814-0001// The package includes built-in error handling
try {
$invoiceId = generateUniqueId('invoice', 'invoices', 'invoice_no');
} catch (\Exception $e) {
// If normal generation fails, package provides fallback
// Fallback format: INVOICE-1692012345-1234 (timestamp-based)
Log::error("ID generation failed: " . $e->getMessage());
// You still get a unique ID, just less pretty
}// Solution: Add the prefix to your database
DB::table('id_prefixes')->insert([
'name' => 'your-type',
'prefix' => 'YOUR-PREFIX'
]);// Solution: Ensure your table has the target column
Schema::table('your_table', function (Blueprint $table) {
$table->string('your_id_column')->unique();
});Parameters:
$type: Type name fromid_prefixestable (e.g., 'invoice')$table: Target database table name$column: Target column name for the ID
Returns: Formatted unique ID (e.g., 'INV-20250814-0001')
Throws: \Exception if type not found in database
Parameters:
$prefix: Direct prefix string (e.g., 'INV', 'CUSTOM')$table: Target database table name$column: Target column name for the ID
Returns: Formatted unique ID with custom prefix
Class method equivalent to generateUniqueId() helper function.
Class method equivalent to generateUniqueIdWithPrefix() helper function.
- PHP 8.2 or higher
- Laravel 11.0 or higher
- MySQL, PostgreSQL, SQLite, or SQL Server
- PREFIX: 2-10 characters identifying the document type
- YYYYMMDD: Date in ISO format (e.g., 20250814 for August 14, 2025)
- XXXX: 4-digit sequential number starting from 0001 each day
| Document Type | Generated ID | Description |
|---|---|---|
| Invoice | INV-20250814-0001 |
First invoice of August 14, 2025 |
| Complaint | CMP-20250814-0001 |
First complaint of August 14, 2025 |
| Order | ORD-20250814-0053 |
53rd order of August 14, 2025 |
| Custom | CUSTOM-20250814-0001 |
Custom prefix example |
We welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/alimarchal/id-generator.git
cd id-generator
composer installIf you find a bug or have a feature request, please open an issue on GitHub.
This package is open-sourced software licensed under the MIT license.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: kh.marchal@gmail.com
- Laravel UUID - For UUID generation
- Laravel Hashids - For URL-safe ID encoding
Made with ❤️ for the Laravel community by Ali Raza Marchal