RoundlyConsulting\Credits\Events\CreditsModified is dispatched after every recorded change. It carries the creditable, the new Credit row and the resulting balance:
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Credits\Events\CreditsModified;
Event::listen(function (CreditsModified $event): void {
// $event->creditable, $event->credit, $event->balance
});Payload
final class CreditsModified
{
use Dispatchable;
public function __construct(
public readonly Model&Creditable $creditable,
public readonly Credit $credit,
public readonly int $balance, // the bucket's balance this change produced
) {}
}balance is the balance of the bucket that changed — read it from $event->credit->bucket — not a total across buckets. It is the balance this change produced, read under the owner lock inside the change’s transaction, so a racing change never leaks into it.
When it fires
- After every successful write — add(), deduct(), modify(), setTo() and their Money forms on a scope, the matching trait methods — and for each entity credits:modify changes.
- Not when setCreditsTo() is a no-op because the balance already matches.
- Not when the overdraft guard or a money check refuses the change — nothing was written.
A listener
Send a receipt, update a dashboard or alert on a low balance:
use Illuminate\Support\Facades\Log;
Event::listen(function (CreditsModified $event): void {
Log::info("Balance for {$event->creditable->getKey()} is now {$event->balance}");
if ($event->credit->amount < 0 && $event->balance < 10) {
// $event->credit->bucket is running low — notify the owner
}
});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.