sthira-labs/version-vault
Composer 安装命令:
composer require sthira-labs/version-vault
包简介
A clean, configurable, relation-aware model versioning package for Laravel. Tracks efficient diffs (plus periodic snapshots), records changed paths and metadata, and lets you reconstruct, compare, and rollback any Eloquent model with its relations and pivot data.
README 文档
README
VersionVault is a Laravel package for model versioning that is diff-first, snapshot-assisted, and relation-aware. It captures minimal diffs, supports nested relations (including pivot data), and can reconstruct or rollback historical state.
Features
- Diff-first storage with periodic snapshots
- Nested relations (single, collection, pivot)
- Deterministic changed paths for audits and UI diffs
- Rollback support with persisted changes
- Optional created-by tracking and user relation
- Morph map friendly (stores morph alias when configured)
Requirements
- PHP 8.1+
- Laravel 9+ (tested against Laravel 11 and 12 via orchestra/testbench)
Installation
composer require sthira-labs/version-vault
Publish & Migrate
Publish the config and migrations, then run migrations:
php artisan vendor:publish --provider="SthiraLabs\\VersionVault\\VersionVaultServiceProvider"
php artisan migrate
To publish only the config:
php artisan vendor:publish --provider="SthiraLabs\\VersionVault\\VersionVaultServiceProvider" --tag=config
To publish only the migrations:
php artisan vendor:publish --provider="SthiraLabs\\VersionVault\\VersionVaultServiceProvider" --tag=migrations
Quick Start
use SthiraLabs\VersionVault\Traits\HasVersioning; class Project extends Model { use HasVersioning; public function tasks() { return $this->hasMany(Task::class); } public function versioningConfig(): array { return [ 'name', 'tasks:title' => [ 'users:name,pivot(role)' ], ]; } } $project->recordVersion('created'); $project->recordVersionIfChanged('updated'); $result = $project->reconstructVersion(2); $historic = $result->model; $rollback = $project->rollbackToVersion(2);
Reconstruction Basics
Reconstruction is non-destructive by default: existing loaded relations on the template model are preserved, and only attributes present in the snapshot are applied. Relations not present in the snapshot remain untouched unless you enable attach_unloaded_relations or force_replace_relation.
reconstructVersion() always returns a ReconstructionResult DTO with:
model(Model): the reconstructed model instancechangedPaths(array): populated only when diff paths are enableddiff(array): populated only when diff paths are enabled
When with_diff_paths is enabled, many-relation operations include id-scoped paths:
comments.added,comments.103.addedcomments.removed,comments.102.removedtags.attached,tags.7.attachedtags.detached,tags.6.detached
Relation Tracking Modes
Each relation can be tracked in one of two modes:
reference(default): only foreign keys are tracked; relation attributes are not snapshotted.snapshot: selected relation attributes (and nested relations/pivot data) are snapshotted.
Implicit rule (Option B):
- If a relation config includes
attributes,relations, orpivot, it is treated assnapshot. - Otherwise it defaults to
reference.
To force snapshot explicitly, add mode: snapshot to the relation config.
Example: Reference Mode (FK-only)
public function versioningConfig(): array { return [ 'amount', // Reference mode: only FK tracked (no related attributes) 'owner' => true, 'manager' => true, ]; }
Example: Snapshot Mode (full relation)
public function versioningConfig(): array { return [ 'name', // Snapshot mode (implicit because fields are listed) 'category:name', 'profile:bio', 'tasks:title', 'tags:name,pivot(order)', // Or explicitly: 'owner' => [ 'mode' => 'snapshot', 'attributes' => ['name', 'email'], ], ]; }
Reference Relations in Reconstruction
Reference relations are not hydrated from the snapshot. The foreign key is stored as a normal attribute, so you can eager load after reconstruction:
$result = $project->reconstructVersion(2); $result->model->load('owner', 'manager');
If you want FK-only tracking without listing the relation, you can track the FK attribute directly:
public function versioningConfig(): array { return [ 'name', 'owner_id', ]; }
Snapshot Relations in Reconstruction
Snapshot relations are hydrated from stored data (or explicitly allowed via reconstruct_relations):
$result = $project->reconstructVersion(2, [ 'reconstruct_relations' => ['category', 'tasks', 'tags'], 'attach_unloaded_relations' => true, ]);
Configuration
Config file: config/version-vault.php
snapshot_interval(int): store a full snapshot every N versions (default 10)store_empty(bool): allow storing a version even when no changes are detected (default false)debug(bool): enable structured debug logs (default false)debug_channel(string|null): log channel to use for debug logs (default null)migrations(bool): auto-load package migrations (default true)table_name(string): versions table namemodel(class-string): Version model classuser_model(class-string|null): model used forVersion::user()relation (defaults toauth.providers.users.model)reconstruct(array): default reconstruction optionsreconstruct.hydrate_loaded_relations_only(bool): only hydrate relations already loaded on the template model (default true)reconstruct.preserve_missing_attributes(bool): keep template attributes not present in the snapshot (default true)reconstruct.attach_unloaded_relations(bool): build relations even when not loaded (default false)reconstruct.force_replace_relation(bool): replace relation objects rather than update in-place (default false)reconstruct.with_diff_paths(bool): include diff + changed paths in reconstruction result (default false)reconstruct.reconstruct_relations(array|null): if set, only hydrate the listed relationsreconstruct.prune_missing_many_relations(bool): for loadedhasMany/morphMany/belongsToMany, remove items not present in target version (default true). When false, missing items are kept; if explicit removed/detached ids exist, unrelated stale items are still dropped.bindings(array): override internal services (change detector, snapshot builder, resolver, manager, etc.)
Migration Note
Default relation tracking is now reference mode to avoid creating versions when related model attributes change but the foreign key does not.
If you rely on deep relation snapshots, configure the relation with fields (implicit snapshot) or set mode: snapshot.
Version Records (created_by)
If an authenticated user exists, created_by is recorded on each version. You can also pass an explicit user id as the third argument to recordVersion, recordVersionIfChanged, or forceSnapshot — useful from queue jobs or system actors where Auth::id() is not available.
$project->recordVersion('updated', [], $actorId);
The Version model exposes a createdBy() relation that resolves via version-vault.user_model or falls back to auth.providers.users.model.
Snapshot & Diff Format
See docs/NEW_NODE_FORMAT.md for the exact snapshot/diff schema and examples.
Events
VersionVault dispatches lifecycle events you can listen to:
SthiraLabs\VersionVault\Events\VersionRecordingSthiraLabs\VersionVault\Events\VersionRecordedSthiraLabs\VersionVault\Events\VersionReconstructedSthiraLabs\VersionVault\Events\VersionRollback
Details and payloads are documented in docs/EVENTS.md.
Testing
composer test
Useful Commands
- Install package:
composer require sthira-labs/version-vault - Publish config:
php artisan vendor:publish --provider="SthiraLabs\\VersionVault\\VersionVaultServiceProvider" --tag=config - Publish migrations:
php artisan vendor:publish --provider="SthiraLabs\\VersionVault\\VersionVaultServiceProvider" --tag=migrations - Run migrations:
php artisan migrate - Run tests:
composer test
Development
Local dev option: use the provided docker-compose / Makefile or Laravel Sail.
License
MIT
sthira-labs/version-vault 适用场景与选型建议
sthira-labs/version-vault 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 17 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「Audit」 「versioning」 「laravel」 「history」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 sthira-labs/version-vault 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 sthira-labs/version-vault 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 sthira-labs/version-vault 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Log adding/updating/deleting of elements
Doctrine ORM provider for the auditor audit-log library.
Versioning behaviour for eloquent models
A decent, standards-compliant, Semantic Versioning (SemVer) parser and library
PB Web Media Audit Bundle for Symfony
A Laravel package for managing model drafts.
统计信息
- 总下载量: 5
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 41
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-03-17