PHP数据版本控制与审计追踪
2026/6/3 8:37:16 网站建设 项目流程

PHP数据版本控制与审计追踪

数据版本控制记录数据的每一次变更,支持回溯到任意历史版本。今天说说PHP中数据版本控制和审计追踪的实现。

数据版本控制的核心是保存数据变更的历史记录。

```php
class VersionedEntity
{
private PDO $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
$this->initSchema();
}

private function initSchema(): void
{
$this->pdo->exec("
CREATE TABLE IF NOT EXISTS entity_versions (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
entity_type VARCHAR(100) NOT NULL,
entity_id INT NOT NULL,
version INT NOT NULL,
data JSON NOT NULL,
changed_by INT,
change_reason VARCHAR(500),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_entity_version (entity_type, entity_id, version),
INDEX idx_entity (entity_type, entity_id)
)
");
}

public function saveVersion(string $entityType, int $entityId, array $data, int $changedBy = 0, string $reason = ''): void
{
$nextVersion = $this->getNextVersion($entityType, $entityId);

$stmt = $this->pdo->prepare("
INSERT INTO entity_versions (entity_type, entity_id, version, data, changed_by, change_reason)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([$entityType, $entityId, $nextVersion, json_encode($data), $changedBy, $reason]);
}

public function getVersion(string $entityType, int $entityId, int $version): ?array
{
$stmt = $this->pdo->prepare("
SELECT * FROM entity_versions
WHERE entity_type = ? AND entity_id = ? AND version = ?
");
$stmt->execute([$entityType, $entityId, $version]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? $row : null;
}

public function getHistory(string $entityType, int $entityId): array
{
$stmt = $this->pdo->prepare("
SELECT version, changed_by, change_reason, created_at
FROM entity_versions
WHERE entity_type = ? AND entity_id = ?
ORDER BY version DESC
");
$stmt->execute([$entityType, $entityId]);
return $stmt->fetchAll();
}

public function rollback(string $entityType, int $entityId, int $version): ?array
{
$versionData = $this->getVersion($entityType, $entityId, $version);
if ($versionData === null) return null;

return json_decode($versionData['data'], true);
}

public function diff(string $entityType, int $entityId, int $version1, int $version2): array
{
$v1 = $this->getVersion($entityType, $entityId, $version1);
$v2 = $this->getVersion($entityType, $entityId, $version2);

if (!$v1 || !$v2) return [];

$data1 = json_decode($v1['data'], true);
$data2 = json_decode($v2['data'], true);

$diff = [];
foreach ($data2 as $key => $value) {
if (!isset($data1[$key]) || $data1[$key] !== $value) {
$diff[$key] = ['old' => $data1[$key] ?? null, 'new' => $value];
}
}

return $diff;
}

private function getNextVersion(string $entityType, int $entityId): int
{
$stmt = $this->pdo->prepare("
SELECT COALESCE(MAX(version), 0) + 1
FROM entity_versions
WHERE entity_type = ? AND entity_id = ?
");
$stmt->execute([$entityType, $entityId]);
return (int)$stmt->fetchColumn();
}
}

class VersionedUserService
{
private PDO $pdo;
private VersionedEntity $versions;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
$this->versions = new VersionedEntity($pdo);
}

public function createUser(array $data, int $operatorId = 0): int
{
$stmt = $this->pdo->prepare("INSERT INTO users (name, email, role) VALUES (?, ?, ?)");
$stmt->execute([$data['name'], $data['email'], $data['role'] ?? 'user']);
$id = (int)$this->pdo->lastInsertId();

$this->versions->saveVersion('user', $id, $data, $operatorId, '创建用户');
return $id;
}

public function updateUser(int $id, array $data, int $operatorId = 0): void
{
$oldStmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ?");
$oldStmt->execute([$id]);
$oldData = $oldStmt->fetch(PDO::FETCH_ASSOC);

$sets = [];
$params = [];
foreach ($data as $key => $value) {
$sets[] = "{$key} = ?";
$params[] = $value;
}
$params[] = $id;

$this->pdo->prepare("UPDATE users SET " . implode(', ', $sets) . " WHERE id = ?")->execute($params);

$this->versions->saveVersion('user', $id, array_merge($oldData, $data), $operatorId, '更新用户');
}

public function getUserHistory(int $id): array
{
return $this->versions->getHistory('user', $id);
}
}

$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$userService = new VersionedUserService($pdo);

$userId = $userService->createUser(['name' => '张三', 'email' => 'test@test.com'], 1);
echo "用户已创建 ID: {$userId}\n";

$userService->updateUser($userId, ['name' => '张三丰'], 1);
echo "用户已更新\n";

$history = $userService->getUserHistory($userId);
echo "变更历史:\n";
foreach ($history as $h) {
echo " 版本 {$h['version']}: {$h['change_reason']} ({$h['created_at']})\n";
}
?>

数据版本控制是审计和数据恢复的基础。每次数据变更都保存完整快照,可以回溯到任意历史版本。变更记录包括修改人、修改时间和修改原因,便于审计追踪。这种模式特别适合对数据完整性要求高的业务场景。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询