本文目录导读:

PHP 数据版本控制(Data Version Control)主要有两种场景:数据库记录变更追踪 和 文件/数据集的版本管理,下面分别介绍实现方案。
数据库记录变更追踪(类似审计日志)
数据库触发 + 历史表(最常用)
原理:为每个需要版本控制的表创建对应的 _history 表,使用触发器或应用层逻辑记录每次变更。
示例(MySQL + PHP):
-- 原表
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,VARCHAR(255),
content TEXT,
updated_at TIMESTAMP
);
-- 历史表(存储每次变更)
CREATE TABLE articles_history (
history_id INT PRIMARY KEY AUTO_INCREMENT,
article_id INT,VARCHAR(255),
content TEXT,
version INT,
action ENUM('INSERT', 'UPDATE', 'DELETE'),
changed_by VARCHAR(100),
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
PHP 实现:
class VersionableModel {
private $db;
private $table;
function save($data, $id = null) {
if ($id) {
// 1. 读取当前版本号
$current = $this->db->query(
"SELECT version FROM {$this->table} WHERE id = ?", [$id]
)->fetch();
// 2. 保存旧数据到历史表
$this->db->query(
"INSERT INTO {$this->table}_history (article_id, title, content, version, action, changed_by)
SELECT id, title, content, version, 'UPDATE', ?
FROM {$this->table} WHERE id = ?",
[$_SESSION['user'], $id]
);
// 3. 更新原表
$newVersion = $current['version'] + 1;
$this->db->query(
"UPDATE {$this->table} SET title=?, content=?, version=? WHERE id=?",
[$data['title'], $data['content'], $newVersion, $id]
);
} else {
// 新记录,版本号=1
$this->db->query(
"INSERT INTO {$this->table} (title, content, version) VALUES (?, ?, 1)",
[$data['title'], $data['content']]
);
// 同时插入历史
$newId = $this->db->lastInsertId();
$this->db->query(
"INSERT INTO {$this->table}_history (article_id, title, content, version, action, changed_by)
VALUES (?, ?, ?, 1, 'INSERT', ?)",
[$newId, $data['title'], $data['content'], $_SESSION['user']]
);
}
}
// 获取某个版本
function getVersion($id, $version) {
return $this->db->query(
"SELECT * FROM {$this->table}_history
WHERE article_id = ? AND version = ?",
[$id, $version]
)->fetch();
}
}
JSON 快照存储(适合非结构数据)
将所有历史版本以 JSON 格式保存在单独的 versions 表:
class SnapshotVersion {
private $table = 'entity_versions';
function saveVersion($entityType, $entityId, $data) {
$version = $this->getNextVersion($entityType, $entityId);
$this->db->insert($this->table, [
'entity_type' => $entityType,
'entity_id' => $entityId,
'version' => $version,
'snapshot' => json_encode($data),
'created_by' => current_user(),
'created_at' => date('Y-m-d H:i:s')
]);
}
function compareVersions($entityType, $entityId, $v1, $v2) {
$data1 = json_decode($this->getVersion($entityType, $entityId, $v1)['snapshot'], true);
$data2 = json_decode($this->getVersion($entityType, $entityId, $v2)['snapshot'], true);
return array_diff_assoc($data1, $data2);
}
}
使用现有 PHP 包(推荐)
- Laravel Auditing:专为 Laravel 设计的审计日志,自动追踪所有模型变更。
- Versionable:轻量级 PHP 库,支持回滚和版本比较。
- Doctrine ORM:内置 Entity 版本控制(使用
@Version注解)。
文件/数据集的版本管理(类似 Git for Data)
自建文件版本库
class FileVersionControl {
private $repoPath;
function commit($filePath, $message) {
$hash = md5_file($filePath);
$versionDir = $this->getVersionDir($filePath);
// 1. 复制文件到版本目录
copy($filePath, "$versionDir/$hash");
// 2. 记录元信息
$this->logCommit($filePath, $hash, $message);
}
function checkout($filePath, $versionHash) {
$versionDir = $this->getVersionDir($filePath);
$source = "$versionDir/$versionHash";
if (file_exists($source)) {
copy($source, $filePath);
} else {
throw new Exception("Version $versionHash not found");
}
}
function diff($filePath, $v1, $v2) {
$dir = $this->getVersionDir($filePath);
return shell_exec("diff $dir/$v1 $dir/$v2");
}
}
集成 DVC(Data Version Control)
DVC 是专为 ML 项目设计的数据版本控制工具,PHP 项目可通过命令行调用:
class DVCWrapper {
function add($path) {
exec("dvc add $path 2>&1", $output, $code);
return $code === 0;
}
function commit($message) {
exec("git add .dvc && git commit -m " . escapeshellarg($message));
}
function checkout($version) {
exec("git checkout $version -- *.dvc");
exec("dvc checkout");
}
}
使用对象存储版本控制(S3/GCS)
class ObjectStoreVersions {
private $s3;
function save($bucket, $key, $data) {
// 利用 S3 内置版本控制(需开启)
$this->s3->putObject([
'Bucket' => $bucket,
'Key' => $key,
'Body' => $data
]);
// 自动生成 versionId
}
function listVersions($bucket, $key) {
$versions = $this->s3->listObjectVersions([
'Bucket' => $bucket,
'Prefix' => $key
]);
return $versions['Versions'];
}
function restore($bucket, $key, $versionId) {
// 复制指定版本到当前版本
$this->s3->copyObject([
'Bucket' => $bucket,
'Key' => $key,
'CopySource' => "$bucket/$key?versionId=$versionId"
]);
}
}
实战建议
| 场景 | 推荐方案 | 理由 | |------|----------|------|管理系统(CMS) | 历史表 + 触发器 | 简单可靠,SQL 查询方便 | | 电商订单变更 | JSON 快照 | 数据结构不固定,方便扩展 | | Team 协作的文章编辑 | Versionable 包 | 开箱即用,支持冲突检测 | | ML 数据集管理 | DVC | 针对大数据集优化,与 Git 配合 | | 文件服务器 | S3 版本控制 | 云原生,免维护 |
性能优化:
- 历史表定期归档(按月/周分区)
- 只记录变更字段,而非整行
- 使用异步队列处理版本写入
安全考虑:
- 限制版本保留数量(如最多 100 个版本)
- 版本数据加密存储
- 版本回滚操作需二次确认
根据你的具体数据规模和复杂度,可以选择上述方案灵活组合,对于大多数 PHP 应用,历史表 + 应用层控制 是最均衡的选择。