---
title: "Custom model & translations — Credits for Laravel | Roundly"
description: "Swap in your own Credit subclass through credits.model, and publish the exception messages to translate or reword them."
url: https://roundly-consulting.com/open-source/docs/credits-for-laravel/extending
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Credits for Laravel](https://roundly-consulting.com/open-source/docs/credits-for-laravel.md)

# Custom model & translations

## Your own ledger model

The Credit model is deliberately not final. Extend it to add relations, accessors or observers:

```php
namespace App\Models;

use RoundlyConsulting\Credits\Models\Credit;

class LedgerEntry extends Credit
{
    protected $table = 'credits';

    // your own relations, accessors, observers ...
}
```

Then point the config at it — the relation, the balance reads and the scopes all use the configured class:

```php
// config/credits.php
'model' => App\Models\LedgerEntry::class,
```

- A key that is not set — absent, null or blank — resolves the packaged Credit.
- Anything else must be Credit or a subclass of it — the ledger’s scopes and the bucket and amount columns depend on it — or the toolkit’s InvalidConfigurationException is thrown naming the key. A foreign class is never silently replaced.
- The ledger lives on one connection: your model’s own $connection when it sets one, else the owner’s. Balance and total reads, the owner lock and the transaction around each change all run there, so an owner on a tenant connection keeps its ledger beside it. The migration creates credits and credit\_locks together — run it on that connection.

## Translations

The exception messages live in the credits::messages translation group and ship in English and Slovak, so with the application locale set to sk they read in Slovak. Publish them with the credits-translations tag and edit lang/vendor/credits/{en,sk}/messages.php — or add a locale folder next to them:

```php
// lang/vendor/credits/en/messages.php
return [
    'insufficient' => 'Insufficient credits: tried to deduct :requested but only :available are available.',
    'insufficient_above_minimum' => 'Insufficient credits: tried to deduct :requested but only :spendable can be spent above the minimum balance of :minimum.',
    'not_denominated' => 'The credits bucket [:bucket] is not denominated in a currency; map it in credits.currencies to use money amounts.',
];
```

InsufficientCreditsException renders :requested as an absolute amount and, with a floor other than 0, uses insufficient\_above\_minimum with :spendable and :minimum; BucketNotDenominatedException fills :bucket with the resolved bucket name. A line your published copy lacks is read from the package.

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

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

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/credits-for-laravel.md)
