PHPackages                             peters-development/laravel-model-logger - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. peters-development/laravel-model-logger

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

peters-development/laravel-model-logger
=======================================

Lightweight polymorphic model activity logging for Laravel.

v2.0.0(1mo ago)04MITPHPPHP ^8.3

Since Mar 14Pushed 1mo agoCompare

[ Source](https://github.com/Peters-Development/laravel-model-logger)[ Packagist](https://packagist.org/packages/peters-development/laravel-model-logger)[ RSS](/packages/peters-development-laravel-model-logger/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (10)Versions (3)Used By (0)

Laravel Model Logger
====================

[](#laravel-model-logger)

Lightweight polymorphic model activity logging for Laravel.

- **Zero-config for simple apps** — `composer require`, `php artisan migrate`, start logging.
- **Channels for advanced apps** — route logs to different tables, connections, or morph key types (numeric/uuid/ulid) when multiple packages or databases are involved.

Installation
------------

[](#installation)

```
composer require peters-development/laravel-model-logger
php artisan migrate
```

The service provider is auto-discovered. The default migration creates a `model_logs` table on your default connection.

Basic usage
-----------

[](#basic-usage)

Add the `HasModelLogs` trait to any Eloquent model:

```
use PetersDevelopment\ModelLogger\HasModelLogs;

class Order extends Model
{
    use HasModelLogs;
}
```

Log activity:

```
$order->log('Order was shipped');
$order->log('Payment received', ['amount' => 99.99, 'method' => 'ideal']);

$order->logs;        // MorphMany — collection of ModelLog
$log = $order->log('Status changed', ['from' => 'pending', 'to' => 'shipped']);
```

The authenticated user is automatically recorded. Meta is stored as JSON.

### Querying

[](#querying)

```
use PetersDevelopment\ModelLogger\ModelLog;

$log->user;                                // User model that performed the action
$logsByUser = ModelLog::forUser($userId)->get();
```

Configuration
-------------

[](#configuration)

Publish to customise:

```
php artisan vendor:publish --tag=model-logger-config
```

The config is built around **channels**. Each channel owns its own table, connection, and morph-key type. Simple apps use the single bundled `default` channel and never touch this:

```
// config/model-logger.php (default — works without publishing)
return [
    'default' => env('MODEL_LOGGER_DEFAULT_CHANNEL', 'default'),

    'channels' => [
        'default' => [
            'table' => 'model_logs',
            'connection' => null,           // null = Laravel default
            'morph_key_type' => 'numeric',  // 'numeric' | 'uuid' | 'ulid'
            'user_model' => null,           // null = config('auth.providers.users.model')
        ],
    ],
];
```

Channels (advanced)
-------------------

[](#channels-advanced)

Channels let multiple loggers coexist in one app without colliding. Typical use cases:

- A multi-tenant SaaS that wants **landlord** auth-events on one connection and **tenant** business-events on another.
- A package (e.g. a billing or auth package) that ships its own table-prefixed channel without overwriting the host app's logs.
- An app with **UUID** or **ULID** keyed models that wants properly-sized morph columns.

### Declaring a channel

[](#declaring-a-channel)

Add a channel entry to your published config:

```
// config/model-logger.php
return [
    'default' => 'default',

    'channels' => [
        'default' => [
            'table' => 'model_logs',
            'connection' => null,
            'morph_key_type' => 'numeric',
            'user_model' => null,
        ],
        'auth' => [
            'table' => 'auth_logs',
            'connection' => 'landlord',
            'morph_key_type' => 'numeric',
            'user_model' => \App\Models\User::class,
        ],
    ],
];
```

### Routing a model's logs to a channel

[](#routing-a-models-logs-to-a-channel)

Override `getModelLogChannel()`:

```
class User extends Authenticatable
{
    use HasModelLogs;

    public function getModelLogChannel(): string
    {
        return 'auth';
    }
}
```

`$user->log(...)` and `$user->logs` now read/write the `auth` channel's table on the `landlord` connection.

### Creating the channel's table

[](#creating-the-channels-table)

Write a migration on the channel's target connection. The package ships a schema helper so you don't have to copy column definitions:

```
use PetersDevelopment\ModelLogger\Schema\ModelLogsBlueprint;

return new class extends Migration {
    public function up(): void
    {
        Schema::connection('landlord')->create('auth_logs', function (Blueprint $table) {
            ModelLogsBlueprint::columns($table, morphKeyType: 'numeric');
        });
    }

    public function down(): void
    {
        Schema::connection('landlord')->dropIfExists('auth_logs');
    }
};
```

### Packages that ship their own channel

[](#packages-that-ship-their-own-channel)

A consuming package can register its own channel from its service provider so it never clobbers the host app's `default`:

```
public function register(): void
{
    config()->set('model-logger.channels.mypackage', [
        'table' => 'mypackage_logs',
        'connection' => config('mypackage.database.connection'),
        'morph_key_type' => 'numeric',
    ]);
}
```

Then every model in the package overrides `getModelLogChannel()` to return `'mypackage'`.

morph\_key\_type
----------------

[](#morph_key_type)

ValueWhen to use`numeric`Default. Bigint auto-increment IDs — fits ~95% of Laravel apps.`uuid`Models keyed by UUID.`ulid`Models keyed by ULID (Laravel's `HasUlids` trait).A single app can mix all three by using one channel per key type.

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance94

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~73 days

Total

2

Last Release

31d ago

Major Versions

v1.0.0 → v2.0.02026-05-27

PHP version history (2 changes)v1.0.0PHP ^8.2

v2.0.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/d695a6309a631e6fba6b8307d97dcfe1ba9ed70d7d8894cf3d5e7bf1c0d634fa?d=identicon)[BasHJPeters](/maintainers/BasHJPeters)

---

Top Contributors

[![BasHJPeters](https://avatars.githubusercontent.com/u/74082184?v=4)](https://github.com/BasHJPeters "BasHJPeters (7 commits)")

---

Tags

laravellaravel-frameworklaravel-loggerlaravel-logginglaravel-packagepackagephp

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/peters-development-laravel-model-logger/health.svg)

```
[![Health](https://phpackages.com/badges/peters-development-laravel-model-logger/health.svg)](https://phpackages.com/packages/peters-development-laravel-model-logger)
```

###  Alternatives

[spatie/laravel-health

Monitor the health of a Laravel application

87411.3M153](/packages/spatie-laravel-health)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[hasinhayder/tyro

Tyro - The ultimate Authentication, Authorization, and Role &amp; Privilege Management solution for Laravel 12 &amp; 13

6753.6k5](/packages/hasinhayder-tyro)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[wearepixel/laravel-cart

A cart implementation for Laravel

1355.6k](/packages/wearepixel-laravel-cart)[label84/laravel-auth-log

Log user authentication actions in Laravel.

3657.7k](/packages/label84-laravel-auth-log)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
