Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yekhlakov committed Apr 28, 2021
1 parent f9acb4c commit 5258871
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# History for Laravel Models

Easily add keeping track of model modifications.

## Installation

1. Add `"tochka-developers/model-history":"^0.1"` to the `require` section
of your `composer.json`

2. Publish package assets:
```shell
php artisan vendor:publish
```
3. You may now edit the config file `model-history.php` to specify
the name of the table to store history records. Please do it _before_
running the migrations. Default name is `history` which is quite reasonable.

4. Use `\Tochka\ModelHistory\HasHistory` trait in your model.

## History structure

History records for all tracked models are stored in the same table
specified in the config file (`history` is the default name).
Each record contains the following data:
- `changed_at` - time of modification;
- `entity_name` - name of the table containing tracked model records;
- `entity_id` - ID of the row in the tracked table the history entry relates to;
- `action` - type of modification. The possible values are `create`, `update`,
`delete` and `restore`.
- `new_data` - a JSON containing _new_ values. Therefore each history record is
essentially a diff to the previous version of the model.

## Warning

The history table always grows and is NEVER CLEANED UP by this package.
Please consider the possibility of the history table becoming the largest
in your database and occupying more space than all other tables
ultimately exhausting all available disk space.
23 changes: 23 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "tochka-developers/model-history",
"description": "Simple history for Laravel models",
"type": "package",
"require": {
"php": "^7.4",
"ext-json": "*",
"ext-pdo": "*",
"laravel/framework": "^5.8 || ^6.0 || ^7.0 || ^8.0"
},
"autoload": {
"psr-4": {
"Tochka\\ModelHistory\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"Tochka\\ModelHistory\\ModelHistoryServiceProvider"
]
}
}
}
6 changes: 6 additions & 0 deletions config/model-history.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

return [
// The table where the history records are kept
'table_name' => 'history',
];
41 changes: 41 additions & 0 deletions database/migrations/2021_04_28_111111_create_history_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Tochka\ModelHistory\HistoryObserver;

/**
* Create table for history records
*/
class CreateHistoryTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(HistoryObserver::getTableName(), function (Blueprint $table) {
$table->increments('id');
$table->string('entity_name');
$table->integer('entity_id');
$table->string('action');
$table->text('new_data')->nullable();
$table->timestamp('changed_at');

$table->index(['entity_name', 'entity_id']);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists(HistoryObserver::getTableName());
}
}
15 changes: 15 additions & 0 deletions src/HasHistory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Tochka\ModelHistory;

/**
* Use this in your model to enable saving history entries
* @codeCoverageIgnore
*/
trait HasHistory
{
public static function bootHasHistory(): void
{
static::observe(HistoryObserver::class);
}
}
62 changes: 62 additions & 0 deletions src/HistoryObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Tochka\ModelHistory;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
* This listens for model events and produces a history record for each action on the model in question.
*/
class HistoryObserver
{
public const ACTION_CREATE = 'create';
public const ACTION_UPDATE = 'update';
public const ACTION_DELETE = 'delete';
public const ACTION_RESTORE = 'restore';

public function created(Model $model): void
{
self::saveData($model, self::ACTION_CREATE);
}

public function updated(Model $model): void
{
self::saveData($model, self::ACTION_UPDATE);
}

public function deleted(Model $model): void
{
self::saveData($model, self::ACTION_DELETE);
}

public function restored(Model $model): void
{
self::saveData($model, self::ACTION_RESTORE);
}

public static function saveData(Model $model, string $action): void
{
$entity_name = $model->getTable();
$entity_id = $model->{$model->getKeyName()};
try {
$query = DB::table(self::getTableName());

$query->insert([
'entity_name' => $entity_name,
'entity_id' => $entity_id,
'action' => $action,
'new_data' => \json_encode($model->getDirty()),
'changed_at' => \date('Y-m-d H:i:s'),
]);
} catch (\Throwable $t) {
Log::error('Unable to save history entry', ['entity_name' => $entity_name, 'entity_id' => $entity_id, 'message' => $t->getMessage()]);
}
}

public static function getTableName(): string
{
return config('model-history.table_name', 'history');
}
}
22 changes: 22 additions & 0 deletions src/ModelHistoryServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Tochka\ModelHistory;

use Illuminate\Support\ServiceProvider;

/**
* Integration
*/
class ModelHistoryServiceProvider extends ServiceProvider
{
public function boot(): void
{
$this->publishes([
__DIR__ . '/../config/model-history.php' => config_path('model-history.php'),
], 'config');

$this->publishes([
__DIR__ . '/../database/migrations/' => database_path('migrations'),
], 'migrations');
}
}

0 comments on commit 5258871

Please sign in to comment.