PHPackages                             bernskiold/laravel-blame - 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. [Database &amp; ORM](/categories/database)
4. /
5. bernskiold/laravel-blame

ActiveLibrary[Database &amp; ORM](/categories/database)

bernskiold/laravel-blame
========================

Automatically track which user created and last updated your Eloquent models, with relations and schema macros.

1.0.0(1mo ago)066↓25%[1 PRs](https://github.com/bernskiold/laravel-blame/pulls)MITPHPPHP ^8.2CI passing

Since Jun 6Pushed 1mo agoCompare

[ Source](https://github.com/bernskiold/laravel-blame)[ Packagist](https://packagist.org/packages/bernskiold/laravel-blame)[ Docs](https://github.com/bernskiold/laravel-blame)[ RSS](/packages/bernskiold-laravel-blame/feed)WikiDiscussions main Synced 1w ago

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

Know who created, updated and deleted your Eloquent models
==========================================================

[](#know-who-created-updated-and-deleted-your-eloquent-models)

[![Latest Version on Packagist](https://camo.githubusercontent.com/ca823e26ee9818f2a553fda6adb5141da02c62e16a571c482f3698d1327872f1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6265726e736b696f6c642f6c61726176656c2d626c616d652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bernskiold/laravel-blame)[![GitHub Tests Action Status](https://camo.githubusercontent.com/e20c92f546246d16c9a1606b56cac697d3c6a0516f7eca6049f9bbb580abbc27/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6265726e736b696f6c642f6c61726176656c2d626c616d652f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/bernskiold/laravel-blame/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/8d34a6b546076f104e782eeb2a9a3af06265ac95247731dd14ba46f2c93afe69/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6265726e736b696f6c642f6c61726176656c2d626c616d652f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/bernskiold/laravel-blame/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/9bda9e165e90dd78d221f10e83832484e2b347f8967f2f091f2854dee9df3635/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6265726e736b696f6c642f6c61726176656c2d626c616d652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/bernskiold/laravel-blame)

"Who changed this?" is a question every serious application eventually has to answer. This package quietly records the user behind each create, update and soft-delete — no manual `created_by_id = auth()->id()` scattered through your controllers, no forgetting to set it on that one form.

```
class Post extends Model
{
    use Blameable;
}

$post->createdBy;   // the user who created it
$post->updatedBy;   // the user who last touched it
```

Add a trait, add the columns, and the right user id is captured automatically on every save — with relations ready for eager loading and display.

Why you'll like it
------------------

[](#why-youll-like-it)

- **Set-and-forget.** The acting user is captured through model events on create, update, soft-delete and restore. You never wire `auth()->id()` by hand again.
- **Pick exactly what you need.** Track the creator, the updater, the deleter — or all three with the combined `Blameable` trait.
- **Relations included.** `createdBy()`, `updatedBy()` and `deletedBy()` are ready to eager-load and render.
- **Sensible, safe defaults.** The creator is only set when empty (so you can override it), and the updater is left untouched when no user is authenticated — a background job won't wipe the last known editor.
- **Works anywhere.** A pluggable resolver lets you record the right user from queues, commands and imports, not just web requests.
- **Configurable to the column.** Bring your own column names, user model, and foreign key behaviour — globally or per model.
- **Tidy migrations.** `$table->blameable()` adds the columns (and foreign keys) in one line.

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

[](#installation)

You can install the package via Composer:

```
composer require bernskiold/laravel-blame
```

If you'd like to change the column names, the user model, or the foreign key behaviour, publish the config:

```
php artisan vendor:publish --tag=blame-config
```

Schema
------

[](#schema)

Add the columns with the blueprint macros:

```
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->blameable();   // created_by_id + updated_by_id (nullable, nullOnDelete)
    $table->timestamps();
});
```

You can also add columns individually with `$table->createdBy()`, `$table->updatedBy()` and `$table->deletedBy()`. Each macro returns the column definition for further chaining, and accepts an explicit column name and a referenced table (handy for cross-database schemas):

```
$table->createdBy('author_id', 'reporting.users');
```

Usage
-----

[](#usage)

Pick the trait that fits the model:

```
use Bernskiold\LaravelBlame\Concerns\Blameable;       // created + updated
use Bernskiold\LaravelBlame\Concerns\TracksCreatedBy; // creator only
use Bernskiold\LaravelBlame\Concerns\TracksUpdatedBy; // updater only
use Bernskiold\LaravelBlame\Concerns\TracksDeletedBy; // soft-delete remover

class Post extends Model
{
    use Blameable;
}
```

That gives you:

```
$post->created_by_id;   // set once, on creation
$post->updated_by_id;   // set on creation and every update

$post->createdBy;       // BelongsTo User
$post->updatedBy;       // BelongsTo User
```

The creating user is only written when the column is empty, so you can override it explicitly. The updating user is **not** overwritten when no authenticated user can be resolved (for example, a queue or console process), preserving the last known editor.

### Tracking the soft-delete remover

[](#tracking-the-soft-delete-remover)

`TracksDeletedBy` records who soft-deleted a row in `deleted_by_id` and clears it again on restore. It only acts on models that also use Laravel's `SoftDeletes` — there's no row to annotate after a hard delete — and it is intentionally **not** bundled into `Blameable`, since most models don't soft-delete:

```
use Bernskiold\LaravelBlame\Concerns\TracksDeletedBy;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes, TracksDeletedBy;
}

$post->deletedBy;   // BelongsTo User
```

Add the column with `$table->deletedBy();`.

### Resolving the acting user

[](#resolving-the-acting-user)

By default the acting user is `auth()->id()`. Override this for contexts without an authenticated user — imports, queues, scheduled commands:

```
use Bernskiold\LaravelBlame\Support\Blame;

Blame::resolveUserIdUsing(fn () => $importJob->triggeredByUserId);
```

The relations point at `config('auth.providers.users.model')` by default; set `blame.user_model` to override.

### Custom column names

[](#custom-column-names)

Globally in `config/blame.php`, or per model with constants:

```
class Post extends Model
{
    use Blameable;

    public const CREATED_BY_COLUMN = 'author_id';
    public const UPDATED_BY_COLUMN = 'editor_id';
}
```

### A note on model events

[](#a-note-on-model-events)

The creating / updating / deleting user is captured through Eloquent model events, so it works for `create()`, `save()`, `update()`, `delete()` and `restore()`. Mass operations that bypass model events — such as `Post::query()->update([...])` or `Post::query()->delete()` — will **not** set the blame columns. Set them explicitly in those queries if you need them.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](SECURITY.md) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Erik Bernskiöld](https://bernskiold.com)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see the [License File](LICENSE.md) for more information.

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance92

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 83.3% 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

Unknown

Total

1

Last Release

48d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8409819?v=4)[Bernskiold](/maintainers/bernskiold)[@bernskiold](https://github.com/bernskiold)

---

Top Contributors

[![ErikBernskiold](https://avatars.githubusercontent.com/u/1166728?v=4)](https://github.com/ErikBernskiold "ErikBernskiold (5 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

auditingblameableeloquentlaravellaravel-packagephplaraveleloquentBlameableauditingcreated\_byupdated\_byblamebernskiold

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/bernskiold-laravel-blame/health.svg)

```
[![Health](https://phpackages.com/badges/bernskiold-laravel-blame/health.svg)](https://phpackages.com/packages/bernskiold-laravel-blame)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[watson/validating

Eloquent model validating trait.

9803.5M55](/packages/watson-validating)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2111.3M18](/packages/reedware-laravel-relation-joins)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.6k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

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