PHPackages                             gazugafan/laravel-changelog - 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. gazugafan/laravel-changelog

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

gazugafan/laravel-changelog
===========================

Database record changelogs for Laravel 5

v1.0.0(9y ago)666MITPHPPHP &gt;=7.0.0

Since Feb 18Pushed 3y ago1 watchersCompare

[ Source](https://github.com/gazugafan/laravel-changelog)[ Packagist](https://packagist.org/packages/gazugafan/laravel-changelog)[ Docs](https://github.com/gazugafan/laravel-changelog)[ RSS](/packages/gazugafan-laravel-changelog/feed)WikiDiscussions master Synced 4w ago

READMEChangelog (1)Dependencies (6)Versions (2)Used By (0)

Laravel Model Changelogs
========================

[](#laravel-model-changelogs)

### Database record changelogging for Laravel 5

[](#database-record-changelogging-for-laravel-5)

Automatically log who did what, when, and from where. Pairs super well with [laravel-temporal](https://github.com/gazugafan/laravel-temporal)!

Requirements
------------

[](#requirements)

- This has only been tested on Laravel 5.4 with PHP 7.1. Let me know if you find it works on older versions!
- Also only tested with MySQL/MariaDB. Let me know if you find it works with other databases!
- No unit tests yet.

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

[](#installation)

Install via Composer...

```
composer require gazugafan/laravel-changelog
```

Add the service provider to the `providers` array in `config/app.php`...

```
'providers' => [
	...
	\Gazugafan\Changelog\ServiceProvider::class
];
```

And add an alias to the `aliases` array in `config/app.php`...

```
'aliases' => [
	...
	'Change' => Gazugafan\Changelog\Facades\Change::class
];
```

Overview
--------

[](#overview)

Changelogged tables get a new `change_id` column, which relates to a new `changes` table to save details about the latest change to a record. Wrapping changes in database transactions allows multiple tables to be affected by the same change. The ID of the authenticated user is automatically logged with each change (if possible), and you can include details like notes and the interface the change took place from.

When paired with [laravel-temporal](https://github.com/gazugafan/laravel-temporal), this will give you the history of every change made to a record, including who made each change and exactly what was changed.

Schema Migration
----------------

[](#schema-migration)

Run the following migration to create the necessary `changes` table...

```
Schema::create('changes', function (Blueprint $table) {
	$table->increments('id');
	$table->timestamps();
	$table->unsignedInteger('user_id')->nullable();
	$table->string('interface', 127)->nullable();
	$table->string('notes', 255)->nullable();
	$table->enum('status', ['pending', 'complete', 'failed'])->default('pending');
	$table->index('status');
});
```

You'll also need to add a `change_id` column to any table you want to log changes in...

```
Schema::table('widgets', function (Blueprint $table) {
	$table->unsignedInteger('change_id')->nullable();
});
```

Model Setup
-----------

[](#model-setup)

To make your model support changelogging, just add the `Gazugafan\Changelog\Changelog` trait to the model's class...

```
class Widget extends Model
{
	use Changelog; //add all the changelog features
}
```

You can also set some model-specific options...

```
class Widget extends Model
{
	use Changelog; //add all the changelog features

	protected $forceChangelogging = true; //set to false to allow saving outside of changes
	protected $changeIDColumn = 'change_id'; //in case you want to use a different column for some reason
}
```

Usage
-----

[](#usage)

#### Logging changes

[](#logging-changes)

To start logging a change, call `Change::begin()`. You can optionally specify the interface and notes to log along with the change...

```
Change::begin('Web API', 'Painting a widget red');
```

This will insert a new change into the `changes` table with a status of `pending`, and automatically fill in the authenticated user's ID if one is available. Next, start doing everything related to your change...

```
$widget = \App\Widget::find(123);
$widget->color = 'red';
$widget->save();

$redPaint = \App\Paint::where('color', 'red')->first();
$redPaint->available -= 1;
$redPaint->save();
```

Whenever you `save()` a model with the `Changelog` trait, the ID of the change in progress will automatically be filled into the the record's `change_id`.

When you're finished with your change, call `Change::commit()`. This will finalize the change by updating its status to `complete`. If the change failed for some reason, you can call `Change::rollBack()` to abandon the change and set its status to `failed`. Here's what the whole thing might look like...

```
try {
	Change::begin('Web API', 'Painting a widget red');

	$widget = \App\Widget::find(123);
	$widget->color = 'red';
	$widget->save();

	$redPaint = \App\Paint::where('color', 'red')->first();
	$redPaint->available -= 1;
	$redPaint->save();

	Change::commit();
} catch (Exception $e) {
	Change::rollBack();
}
```

If this looks similar to how database transactions are handled in Laravel, that's no coincidence! By default, the `Change` methods above will also wrap your change in a transaction. This means if something goes wrong during your change, the entire thing will automatically be rolled back. In other words: either the entire change happens successfully, or the entire thing fails. There's no way for just part of the change to complete. Also just like Laravel transactions, you can use the `transaction` method with a closure...

```
Change::transaction(function (){
	$widget = \App\Widget::find(123);
	$widget->color = 'red';
	$widget->save();

	$redPaint = \App\Paint::where('color', 'red')->first();
	$redPaint->available -= 1;
	$redPaint->save();
}, 'Web API', 'Painting a widget red', 5); //make 5 attempts in case of deadlock
```

If you'd like to disable the use of transactions for some reason, pass `false` as the third parameter to `Change::begin()`...

```
try {
	Change::begin('Web API', 'Painting a widget red', FALSE); //start a change without transactions

	$widget = \App\Widget::find(123);
	$widget->color = 'red';
	$widget->save();

	$redPaint = \App\Paint::where('color', 'derek')->first();
	$redPaint->available -= 1; //there's no "derek" color, dummy! This is gonna blow up!
	$redPaint->save();

	Change::commit();
} catch (Exception $e) {
	//great, now we've somehow painted a widget red without using any red paint.
	//if only we had used transactions, we'd rollback painting the widget red here...
	Change::rollBack(); //but this will still log the change's status as "failed", at least
}
```

The authenticated user's ID is retrieved via `Auth::id()`. If you'd like to override this with your own behavior, you can pass a closure to `Change::authID()`...

```
Change::authID(function(){
	return getMySpecialLoggedInUsersID();
});
Change::begin();
...
```

Pitfalls
--------

[](#pitfalls)

- Unlike normal Laravel database transactions, nested changes are not supported. Attempting to start a change while another change is already in progress will result in an error.

###  Health Score

28

—

LowBetter than 52% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity58

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

Unknown

Total

1

Last Release

3420d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/854538?v=4)[Ken](/maintainers/gazugafan)[@gazugafan](https://github.com/gazugafan)

---

Top Contributors

[![gazugafan](https://avatars.githubusercontent.com/u/854538?v=4)](https://github.com/gazugafan "gazugafan (3 commits)")

---

Tags

changeloglaravellaravel-5-packagelaravel-modelsversioningloglaraveltraitchangelogchange

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/gazugafan-laravel-changelog/health.svg)

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

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M337](/packages/psalm-plugin-laravel)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M91](/packages/mongodb-laravel-mongodb)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M125](/packages/laravel-pulse)[flat3/lodata

OData v4.01 Producer for Laravel

100351.7k](/packages/flat3-lodata)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M123](/packages/roots-acorn)[spatie/laravel-health

Monitor the health of a Laravel application

87511.3M155](/packages/spatie-laravel-health)

PHPackages © 2026

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