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 Autonumber Laravel Package

alfa6661/laravel-autonumber

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require alfa6661/laravel-autonumber
    

    Register the service provider in config/app.php:

    Alfa6661\AutoNumber\AutoNumberServiceProvider::class,
    

    Publish the config:

    php artisan vendor:publish --provider="Alfa6661\AutoNumber\AutoNumberServiceProvider"
    

    Run migrations:

    php artisan migrate
    
  2. First Use Case: Add the AutoNumberTrait to your Eloquent model and implement getAutoNumberOptions():

    use Alfa6661\AutoNumber\AutoNumberTrait;
    
    class Invoice extends Model
    {
        use AutoNumberTrait;
    
        public function getAutoNumberOptions()
        {
            return [
                'prefix' => 'INV-',
                'length' => 8,
                'padding' => '0',
                'field'   => 'invoice_number',
                'format'  => 'Y-m-d-His', // Optional: for dynamic prefixes
            ];
        }
    }
    

    Now, every time you create an Invoice, the invoice_number field will auto-populate with a formatted number (e.g., INV-20230815).


Implementation Patterns

Core Workflows

  1. Basic Auto-Numbering: Use static configurations for simple sequential numbering:

    public function getAutoNumberOptions()
    {
        return [
            'prefix' => 'ORD-',
            'length' => 6,
            'padding' => '0',
            'field'   => 'order_code',
        ];
    }
    

    Output: ORD-000001, ORD-000002, etc.

  2. Dynamic Prefixes with Dates: Leverage the format option for time-based prefixes:

    public function getAutoNumberOptions()
    {
        return [
            'prefix' => 'INV-',
            'length' => 6,
            'padding' => '0',
            'field'   => 'invoice_number',
            'format'  => 'Y', // Year-based prefix (e.g., "INV-20230001")
        ];
    }
    
  3. Custom Logic via Closures: Override getAutoNumber() to inject custom logic:

    use Alfa6661\AutoNumber\AutoNumberTrait;
    
    class Project extends Model
    {
        use AutoNumberTrait;
    
        public function getAutoNumberOptions()
        {
            return [
                'field' => 'project_id',
            ];
        }
    
        public function getAutoNumber()
        {
            $base = parent::getAutoNumber();
            return 'PROJ-' . strtoupper(substr($base, 0, 3)) . '-' . substr($base, 3);
        }
    }
    

    Output: PROJ-ABC-1234.

  4. Batch Processing: Use AutoNumber::generate() for bulk operations:

    $numbers = AutoNumber::generate(Invoice::class, 5); // Generates 5 invoice numbers
    
  5. Soft Deletes Handling: Ensure deleted_at is respected by configuring the query in getAutoNumberOptions():

    public function getAutoNumberOptions()
    {
        return [
            'prefix' => 'DEL-',
            'field'  => 'reference',
            'query'  => function ($query) {
                return $query->whereNull('deleted_at');
            },
        ];
    }
    

Integration Tips

  1. Database Constraints: Add a unique constraint to the auto-number field in migrations:

    Schema::table('invoices', function (Blueprint $table) {
        $table->string('invoice_number')->unique();
    });
    
  2. API Responses: Format auto-numbers in API responses using accessors:

    public function getFormattedInvoiceNumberAttribute()
    {
        return 'Invoice #: ' . $this->invoice_number;
    }
    
  3. Testing: Mock the auto-number generator in tests:

    $invoice = Invoice::factory()->create();
    $this->assertMatchesRegularExpression('/^INV-\d{8}$/', $invoice->invoice_number);
    
  4. Multi-Tenant Support: Scope auto-numbers to tenants via query in getAutoNumberOptions():

    public function getAutoNumberOptions()
    {
        return [
            'field' => 'ticket_number',
            'query' => function ($query) {
                return $query->where('tenant_id', auth()->user()->tenant_id);
            },
        ];
    }
    

Gotchas and Tips

Pitfalls

  1. Race Conditions: Auto-number generation is not thread-safe by default. For high-concurrency apps, use database transactions or a queue:

    DB::transaction(function () {
        $invoice = Invoice::create([...]);
    });
    
  2. Field Name Conflicts: Ensure the field in getAutoNumberOptions() matches the database column exactly (case-sensitive).

  3. Dynamic format Quirks: The format option uses PHP’s date() syntax. Test edge cases (e.g., Y vs. Y-m-d for leap years).

  4. Migration Dependencies: The package adds a auto_number table. If you skip migrations, auto-numbers will fail silently.

  5. Soft Deletes Misconfiguration: Forgetting to include whereNull('deleted_at') in the query option can cause duplicate numbers for soft-deleted records.


Debugging

  1. Log Generation: Temporarily log the auto-number logic:

    public function getAutoNumber()
    {
        $number = parent::getAutoNumber();
        \Log::debug("Generated auto-number: {$number}", ['model' => static::class]);
        return $number;
    }
    
  2. Check the auto_number Table: Inspect auto_number entries for your model:

    SELECT * FROM auto_number WHERE model = 'App\Models\Invoice';
    
  3. Override getNextNumber(): Debug the counter logic:

    public function getNextNumber()
    {
        $next = parent::getNextNumber();
        \Log::debug("Next number for {$this->getAutoNumberField()}: {$next}");
        return $next;
    }
    

Extension Points

  1. Custom Storage: Override getAutoNumberTable() to use a custom table:

    protected function getAutoNumberTable()
    {
        return 'custom_auto_numbers';
    }
    
  2. Event Hooks: Trigger events before/after auto-number generation:

    use Alfa6661\AutoNumber\Events\AutoNumberGenerated;
    
    AutoNumberGenerated::dispatch($this, $this->{$this->getAutoNumberField()});
    
  3. Fallback Logic: Handle generation failures gracefully:

    public function getAutoNumber()
    {
        try {
            return parent::getAutoNumber();
        } catch (\Exception $e) {
            return 'MAN-' . Str::upper(Str::random(6));
        }
    }
    
  4. Multi-Field Auto-Numbers: Combine multiple fields for complex numbering:

    public function getAutoNumber()
    {
        $base = parent::getAutoNumber();
        return $this->category->code . '-' . $base;
    }
    
  5. Localization: Support non-Latin characters in prefixes/padding:

    public function getAutoNumberOptions()
    {
        return [
            'prefix' => 'FACT-',
            'padding' => '۰', // Arabic zero
        ];
    }
    
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