Getting Started
This guide will help you install Ledgerly and record your first audit entry in just a few minutes.
Requirements
Ledgerly requires:
- PHP 8.2+
- Laravel 11+
- A configured database connection
Installation
Install Ledgerly using Composer:
composer require ledgerly-app/core
Run the installation command:
php artisan ledgerly:install
Then run migrations:
php artisan migrate
This creates the table used to store audit entries.
Logging Your First Entry
You can log an entry anywhere in your application:
ledgerly()
->action('billing.invoice.created')
->log();
That’s it — an immutable audit entry has been stored.
Logging with Actor and Target
Most audit entries include context about who performed an action and what was affected.
Example:
ledgerly()
->actor(auth()->user())
->action('billing.invoice.updated')
->target($invoice)
->log();
Ledgerly will store polymorphic references to the actor and target.
Recording Changes (Diffs)
You can record attribute changes:
ledgerly()
->action('billing.invoice.updated')
->withDiff([
'amount' => [1200, 1450],
'status' => ['draft', 'sent'],
])
->log();
Diffs help build activity timelines and audits.
Adding Metadata
You can attach additional structured metadata:
ledgerly()
->action('billing.invoice.sent')
->withMetadata([
'channel' => 'email',
])
->log();
Ledgerly also collects metadata automatically, such as request and environment information.
Using Transactions (Correlation)
To group multiple entries together:
ledgerly()->transaction(function () {
ledgerly()->action('billing.invoice.created')->log();
ledgerly()->action('billing.invoice.sent')->log();
});
Entries inside a transaction share a correlation identifier.
Using Context
Context allows attaching values that apply to multiple entries.
Example:
ledgerly()->context([
'tenant_id' => 42,
]);
ledgerly()->action('billing.invoice.created')->log();
All later entries will include this context in metadata.
Scoped Context
You can limit context to a specific block:
ledgerly()->withContext(['tenant_id' => 42], function () {
ledgerly()->action('billing.invoice.created')->log();
});
Context is automatically restored after the block.
Querying Entries
You can query entries using Eloquent:
use Ledgerly\Core\Models\LedgerEntry;
$entries = LedgerEntry::latest()->take(10)->get();
Ledgerly also provides query scopes:
LedgerEntry::forAction('billing.invoice.updated')->get();
LedgerEntry::forActor($user)->get();
LedgerEntry::forTarget($invoice)->get();
Exporting Entries
Ledger entries can be exported:
$entry->toArray();
$entry->toJson();
Exports preserve metadata, context, and diffs.
What to Read Next
To understand how Ledgerly works internally, continue with: