Named buckets
Credits can be split into independent, named pools on the same entity — for example promotional and purchased credit that should never be spent against each other. On the facade, bucket() narrows the scope; buckets([...]) sums several for reading:
$promo = Credits::for($user)->bucket('promotional'); // an immutable scope — keep and reuse it
$promo->add(100, 'welcome promo');
$promo->balance(); // 100
Credits::for($user)->bucket('purchased')->add(50, 'top-up');
Credits::for($user)->buckets(['promotional', 'purchased'])->balance(); // 150 — summed, read-only
Credits::for($user)->total(); // every bucketEvery trait method accepts the same optional bucket argument:
$user->modifyCredits(100, 'welcome promo', bucket: 'promotional');
$user->modifyCredits(50, 'top-up', bucket: 'purchased');
$user->creditsBalance(bucket: 'promotional'); // 100
$user->creditsBalance(bucket: 'purchased'); // 50Balances are fully isolated per bucket, and the overdraft guard is enforced per bucket — a deduction against purchased cannot draw on promotional credit.
The default bucket
When you omit the bucket, the configured default_bucket ('default') is used for both reads and writes. A bucket-less balance query therefore returns the default bucket only — it does not sum across every bucket:
$user->modifyCredits(25); // lands in the 'default' bucket
$user->creditsBalance(); // 25 (the default bucket only)
$user->creditsBalance(bucket: 'promotional'); // 100Single-pool usage needs no changes: every call without a bucket operates on one pool. setCreditsTo() and hasCredits() take the same bucket argument, and credits:modify has a --bucket= option.
Totals across buckets
When you do want a combined figure, sum a chosen set of buckets or every bucket the entity owns:
// Sum a chosen set of buckets (names are de-duplicated; an empty list returns 0).
$user->creditsBalanceForBuckets(['promotional', 'purchased']); // 150
// Sum every bucket on the entity.
$user->totalCreditsBalance(); // 175
// Both accept an optional point-in-time argument.
$user->totalCreditsBalance(now()->subWeek());
$user->creditsBalanceForBuckets(['promotional', 'purchased'], now()->subWeek());Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.