versions), preserving the main model’s integrity while enabling historical queries.versions table, latest_version column). Schema design must account for:
users and versions.versioned_at, model_id).array_column deprecations, Eloquent API changes).update() on multiple records).newQuery() vs. query())?versions table? Are archiving strategies needed?updating) + a custom versions table achieve similar results with less risk?spatie/laravel-activitylog, laravel-model-versions)?User::email, Product::price).latest_version column to target tables (e.g., users).versions table with columns:
Schema::create('versions', function (Blueprint $table) {
$table->id();
$table->string('model_type'); // e.g., "App\Models\User"
$table->unsignedBigInteger('model_id');
$table->json('changes'); // or serialized array for older PHP
$table->timestamps();
$table->softDeletes();
$table->foreign('model_id')->references('id')->on('users')->onDelete('cascade');
});
(model_type, model_id, versioned_at).Versionable) and configure versioned attributes:
use ProAI\EloquentVersioning\Versionable;
class User extends Model {
use Versionable;
protected $versioned = ['email', 'city'];
protected $versionedTimestamps = true;
protected $versionedSoftDeletes = true;
}
$user = User::find(1);
$user->email = 'new@example.com';
$user->save(); // Triggers versioning.
$versions = $user->versions()->orderBy('created_at', 'desc')->get();
updating, which could interfere with custom event logic.scopeWithVersion($query, $version)).laravel-medialibrary).save() (e.g., laravel-activitylog).BlogPost) to test versioning behavior.User, Order).versions table naming convention (e.g., user_versions) for clarity.user->versions->where('changes->email', 'old@example.com')).versions table).$user->save(); // Logs to `versions` but also to a monitoring tool.
email vs. immutable id).save() operations. Benchmark with production-like data volumes.versions table by model_type or created_at for large datasets.versions_archive after 2 years).DB::table('versions')
->where('created_at', '<', now()->subYears(2))
->update(['archived' => true]);
| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Package incompatibility with Laravel 8+ | Versioning fails silently. | Fork and update package or use alternatives. |
| Unhandled concurrent updates | Lost versions or data corruption. | Implement optimistic locking (e.g., version column). |
versions table bloat |
Slow |
How can I help you explore Laravel packages today?