Weave 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 Id Generator Laravel Package

haruncpi/laravel-id-generator

Laravel ID Generator creates unique, customizable IDs for database records. It supports prefixes, suffixes, fixed lengths, and sequence resets, making it easy to generate invoice, order, ticket, and other formatted IDs without manual tracking.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer (the service provider and IdGenerator facade are auto-discovered):

composer require haruncpi/laravel-id-generator

The only entry point you need is the facade:

use Haruncpi\LaravelIdGenerator\IdGenerator;

$id = IdGenerator::generate([
    'table'  => 'invoices',
    'field'  => 'invoice_no',
    'length' => 10,
    'prefix' => 'INV-',
]);
// "INV-000001"  (length is TOTAL characters, prefix included)
  • table is required; field defaults to id; length defaults to 8; prefix defaults to ''.
  • The output is a zero-padded sequence number appended to your prefix.
  • There is no config file to publish — everything is driven by the options array at the call site.

First use case: an Invoice model with a human-readable number (INV-000123) instead of a raw auto-increment integer. Add the column as a string with a unique index, call the facade in a creating hook, and you're done.

Implementation Patterns

Auto-generate on model creation — the idiomatic wiring:

protected static function booted()
{
    static::creating(function (Invoice $invoice) {
        if (blank($invoice->invoice_no)) {
            $invoice->invoice_no = IdGenerator::generate([
                'table'  => $invoice->getTable(),
                'field'  => 'invoice_no',
                'length' => 15,
                'prefix' => 'INV-' . now()->format('Ymd') . '-',
            ]);
        }
    });
}

Date-scoped / per-tenant counters — change the prefix and pass 'reset_on_prefix_change' => true so the sequence restarts when the prefix (e.g. a new day or tenant) changes:

IdGenerator::generate([
    'table'                 => 'invoices',
    'field'                 => 'invoice_no',
    'length'                => 15,
    'prefix'                => 'INV-' . now()->format('Ymd') . '-',
    'reset_on_prefix_change'=> true,
]);

Custom primary key — if you use the generated ID as the PK, tell Eloquent:

public $incrementing = false;
protected $keyType   = 'string';
protected $primaryKey = 'invoice_no';

Centralize definitions in a helper so the table/field/length/prefix triple isn't duplicated across seeders, factories, tests and model hooks:

class Ids {
    public static function invoice(): string
    {
        return IdGenerator::generate([
            'table' => 'invoices', 'field' => 'invoice_no',
            'length' => 15, 'prefix' => 'INV-' . now()->format('Ymd') . '-',
        ]);
    }
}

Then reference Ids::invoice() from the model, a factory, or a service that imports records.

Retry wrapper for uniqueness — combine with a unique index and catch the duplicate:

DB::transaction(function () use (&$invoice) {
    $invoice->invoice_no = Ids::invoice();
    $invoice->save(); // unique index guarantees the final word
}, 3); // Laravel retries on deadlock, not on unique violations — wrap manually

Gotchas and Tips

  • Race conditions are the real risk. The package reads the current highest value from the table and increments it, with no lockForUpdate or dedicated counter table. Two parallel requests can compute the same ID. Always back the column with a unique index and handle 1252/23000 by regenerating, or serialize generation inside a transaction with row locking.
  • length is total width, not the numeric part. length: 10 with prefix INV- yields six digits. If your prefix grows (dates, tenant codes) and length doesn't, the number silently overflows and IDs get longer than expected.
  • String comparison on MAX(field). Because counting is done on the string column, mixing prefixes or lengths (e.g. a manual INV-9 and generated INV-000010) can produce a surprising "next" value. Keep one prefix format per table.
  • Not concurrency-safe across engines. MySQL MAX() on a heavily written table is also slow as the table grows — consider generating from a dedicated id_sequences table if volume is high.
  • Package age. Last tag is October 2019 (Laravel 5.8/6 era). On modern Laravel (10/11/12) it generally still works because it's a thin query wrapper, but pin the version, test your PHP version, and check the facade alias registers. If you hit issues, the package is small enough to inline the logic into your own trait.
  • Empty tables and soft deletes. Empty table → returns prefix + 000001. Soft-deleted rows still count toward MAX(), which is usually what you want (no ID reuse) but can surprise people expecting a "reset".
  • Testing. In RefreshDatabase tests, factories call Ids::invoice() and hit the real DB — wrap seeding in a transaction so IDs stay predictable, or pass an explicit ID in the factory for assertion stability.
  • Extension point. There is no event hook, so the clean seam is your own Ids/IdGeneratorService class; that's also where you'd swap in a DB-backed counter or Redis::incr if you later outgrow the package.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource