Installation:
composer require proai/eloquent-versioning:~1.0
Publish the migration and config (if needed):
php artisan vendor:publish --provider="ProAI\EloquentVersioning\EloquentVersioningServiceProvider"
Run Migrations:
php artisan migrate
Configure Model:
Extend your Eloquent model with ProAI\EloquentVersioning\Versionable trait and define versioned attributes:
use ProAI\EloquentVersioning\Versionable;
class User extends Model
{
use Versionable;
protected $versioned = ['email', 'city'];
protected $versionedTimestamps = true;
protected $versionedSoftDeletes = true;
}
First Use Case: Create a user and update a versioned attribute:
$user = User::create(['name' => 'John', 'email' => 'john@example.com', 'city' => 'NY']);
$user->update(['city' => 'LA']); // Triggers version creation
Versioned Attribute Updates:
Automatically creates a new version record in versions table when updating versioned fields:
$user->email = 'new@example.com'; // Versioned
$user->save(); // Creates version record
Querying Versions: Retrieve all versions for a model:
$versions = $user->versions()->get();
Get a specific version:
$version = $user->versions()->where('version', 2)->first();
Restoring Versions: Revert to a previous version:
$user->restoreVersion(1); // Restores version 1
Soft Deletes: Enable versionedSoftDeletes to track deletion timestamps in versions.
Timestamps: Enable versionedTimestamps to include created_at/updated_at in versions.
Custom Version Table: Override getVersionTable() in your model for custom naming:
protected function getVersionTable()
{
return 'user_versions';
}
Mass Assignment:
Use update() or fill() with versioned fields—versions are auto-created:
$user->update(['email' => 'updated@example.com', 'city' => 'SF']);
Events:
Listen for versioning.created events to hook into version creation logic:
Event::listen('versioning.created', function ($model, $version) {
// Custom logic after version creation
});
Performance:
limit() or where() to constrain results:
$user->versions()->where('version', '<', 5)->get();
Migration Conflicts:
versions table migration matches the package’s schema (e.g., version, model_type, model_id, changes columns).deleted_at for soft deletes).Soft Deletes:
$versionedSoftDeletes = false) removes deleted_at from versioned fields. Ensure this aligns with your model’s softDeletes setting.Serialization:
json columns or cast attributes:
protected $casts = ['metadata' => 'array'];
Missing Versions:
Check if the model uses the Versionable trait and $versioned attributes are correctly defined.
Verify the versions table exists and has the right schema.
Silent Failures: Enable Laravel’s query logging to debug version creation:
DB::enableQueryLog();
$user->update(['email' => 'test@example.com']);
dd(DB::getQueryLog());
Version Overwrites:
If versions aren’t updating, ensure save() or update() is called (not direct attribute assignment without persistence).
Custom Version Data:
Override getVersionData() to include additional fields in versions:
protected function getVersionData()
{
return array_merge(parent::getVersionData(), ['custom_field' => $this->custom_field]);
}
Version Comparison: Add helper methods to compare versions:
public function diffVersions($version1, $version2)
{
$v1 = $this->versions()->where('version', $version1)->first();
$v2 = $this->versions()->where('version', $version2)->first();
return json_decode($v1->changes, true) - json_decode($v2->changes, true);
}
Version Filtering:
Extend the versions() scope for custom queries:
public function scopeActiveVersions($query)
{
return $query->whereNull('deleted_at');
}
How can I help you explore Laravel packages today?