atannex/generator
A Laravel/PHP code generator package from Atannex that helps scaffold files and boilerplate, streamlining repetitive development tasks and speeding up generation workflows in Laravel projects.
atannex/generator reached its first stable release (v1.0.0), so the API should now be considered settled enough to depend on with a ^1.0 constraint. It targets PHP 8.3+ and Laravel 11/12, which means it can drop onto current LTS-ish projects without shims — but check that your CI matrix and any older satellites (queues, deploy images) are also on 8.3 before adopting.
Minimal path:
composer require atannex/generator
Then, in order:
php artisan vendor:publish --tag=...) and read it end to end. Pattern definitions, sequence storage, and reset cadence are almost certainly configured there rather than in code.Best first use case: invoice/reference numbers, because it exercises every part of the package (prefix, date segment, sequence, uniqueness) and gives you an immediate read on whether the reset cadence matches your accounting period. Staff IDs and vouchers are simpler and can follow.
Define patterns in config, consume them by name. Resist inlining pattern strings at call sites. A named pattern (invoice, voucher, staff_id) in config means a format change is one edit and a code review, not a grep across the codebase. If the package supports per-model formatter classes, use those for anything with business rules (tenant prefixes, year rollover).
Resolve from the container, don't new it up. Constructor-inject the generator into the service that owns numbering. This keeps it swappable in tests and avoids static calls scattered through controllers.
Assign on creation via a model event or a dedicated action, not in the controller. For staff_id/voucher_code-style fields, a creating observer or a Numbered trait keeps the guarantee attached to the model. For invoices, prefer an explicit IssueInvoice action so numbering is a deliberate, auditable step rather than a side effect of Invoice::create().
Pair every generated column with a unique index. The package gives you readable codes, not a uniqueness guarantee under concurrency. The database constraint is the real enforcement; treat a violation as a signal to retry (bounded, a couple of attempts) rather than to panic.
Wrap sequence-consuming writes in a transaction and think about the failure mode. For gapless-required domains (invoices in many jurisdictions) you need the number allocated and the record committed atomically; for domains where gaps are fine (vouchers, tokens), allocate late and accept holes rather than holding locks.
Multi-tenant and per-year scoping. If patterns embed a tenant or year segment, confirm the package resets the sequence per segment rather than globally — otherwise tenant B's first invoice is INV-2025-0047. Test the rollover explicitly by freezing/旅行 time.
Testing. Freeze time (Carbon::setTestNow) for any date-segmented pattern, and assert on shape with a regex rather than an exact string so padding changes don't break unrelated tests. If the package offers a fake or an in-memory sequence driver, use it in feature tests to keep them independent of DB state.
Tokens and vouchers are a different problem. Readable, sequential codes are guessable by design. For anything used as a bearer credential (download links, redemption codes), generate the readable reference and a separate high-entropy secret, or use a random-suffix pattern with enough length. Do not let a sequential pattern become an authorization token.
array or file drivers will silently duplicate numbers in a multi-node setup. Redis with atomic increment, or a DB row with lockForUpdate, are the safe options.php artisan config:cache is your friend in production and your enemy in debugging — a stale cached config is the most common "my new pattern isn't recognised" cause. Always config:clear when a pattern change doesn't appear locally.app.timezone is UTC but your finance team closes months in local time, you'll get year/month boundaries in the wrong place. Pin the timezone explicitly for numbering rather than relying on the default.string lengths (and any char columns) before the first production insert; truncation errors on invoice numbers are painful to remediate.0/O and 1/I/l. If not, normalise on input and document it.lower()/trim() at the boundary saves a lot of support tickets.sprintf('%05d', ...) around it — you'll lose the concurrency handling.^1.0 and read the changelog on minors, since a pattern-language tweak in a 1.x could change generated output without breaking the API contract. Snapshot a handful of expected outputs in a test to catch that.Note: this assessment is based on the v1.0.0 release notes; the concrete class names, config keys, and pattern token syntax should be verified against the README and the published config before committing to an approach.
How can I help you explore Laravel packages today?