NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Require the package. The service provider is auto-discovered, and its two Roundly dependencies — package-toolkit-for-laravel and money-for-laravel — install with it:

composer require roundly-consulting/credits-for-laravel

php artisan vendor:publish --tag="credits-migrations"
php artisan migrate

Publish-only migrations

The package never loads its migrations itself. Publishing copies them into your database/migrations, where you own them — so a bare php artisan migrate before publishing creates nothing. The files are stamped with the current time, so they run after your own tables; publishing again overwrites the same files in place.

The credits migration creates two tables: credits, the ledger, and credit_locks, one small row per owner that serialises concurrent changes (see Overdraft protection). create_credit_holds_table adds credit_holds (see Holds) and create_credit_resets_table adds credit_resets (see Periodic resets).

If your creditable models use UUID or ULID keys, set CREDITS_KEY_TYPE before you migrate — see Key types & schema.

A forward-only migration

Like every Roundly package migration, it has no down(): php artisan migrate:rollback does not drop the tables, and the next migrate then fails on “table already exists”. The published copies are yours — to uninstall, drop credits, credit_locks, credit_holds and credit_resets in a migration of your own, or add a down() to your copies.

Upgrading from 2.0

2.1 adds holds and periodic resets, each with its own table. Publish the migrations again — your existing copy is reused and only the new files are added — and migrate:

php artisan vendor:publish --tag="credits-migrations"   # adds create_credit_holds_table + create_credit_resets_table
php artisan migrate

Nothing else changes. Holds stay off until you set credits.holds.enabled, so an upgrade that has not run the migration keeps working; resets need no switch, only the credit_resets table. The next major release plans to turn holds on by default.

Config and translations

The config file is optional — the package works with zero host configuration. Publish it only to override a default:

php artisan vendor:publish --tag="credits-config"

The exception messages are translatable and ship in English and Slovak. Publish them to lang/vendor/credits to edit them or add locales:

php artisan vendor:publish --tag="credits-translations"

The package exposes exactly three publish tags: credits-migrations, credits-config and credits-translations.

Next steps

  • Add the Creditable interface and the HasCredits trait to a model.
  • Grant and deduct credits with modifyCredits().
  • Split credit into named buckets if different kinds must never be spent against each other.

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 crypto

By 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.