当前位置: 首页 > news >正文

PHP数据迁移与版本控制工具

PHP数据迁移与版本控制工具

数据库迁移是管理数据库结构变更的标准方式。每次修改都记录在迁移文件中,团队按顺序执行。今天说说PHP中数据迁移的实现。

迁移管理器的实现。

```php
class Migration
{
protected PDO $pdo;

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

public function up(): void {}
public function down(): void {}
}

class MigrationRunner
{
private PDO $pdo;
private string $migrationDir;
private string $table = 'migrations';

public function __construct(PDO $pdo, string $migrationDir)
{
$this->pdo = $pdo;
$this->migrationDir = rtrim($migrationDir, '/');
$this->initTable();
}

private function initTable(): void
{
$this->pdo->exec("
CREATE TABLE IF NOT EXISTS {$this->table} (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
batch INT NOT NULL,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
");
}

public function migrate(): void
{
$executed = $this->getExecuted();
$files = $this->getMigrationFiles();
$batch = $this->getNextBatch();
$pending = array_diff($files, $executed);

if (empty($pending)) {
echo "所有迁移已完成\n";
return;
}

foreach ($pending as $file) {
echo "执行: $file\n";
$migration = $this->loadMigration($file);

try {
$this->pdo->beginTransaction();
$migration->up();
$this->record($file, $batch);
$this->pdo->commit();
echo " 完成\n";
} catch (Exception $e) {
$this->pdo->rollBack();
echo " 失败: {$e->getMessage()}\n";
}
}
}

public function rollback(): void
{
$lastBatch = $this->getLastBatch();
if ($lastBatch === 0) {
echo "没有可回滚的迁移\n";
return;
}

$migrations = $this->getBatchMigrations($lastBatch);
foreach (array_reverse($migrations) as $file) {
echo "回滚: $file\n";
$migration = $this->loadMigration($file);
$migration->down();
$this->remove($file);
}
}

private function getExecuted(): array
{
return $this->pdo->query("SELECT migration FROM {$this->table}")->fetchAll(PDO::FETCH_COLUMN);
}

private function getMigrationFiles(): array
{
$files = glob($this->migrationDir . '/*.php');
sort($files);
return array_map('basename', $files);
}

private function getNextBatch(): int
{
return (int)$this->pdo->query("SELECT COALESCE(MAX(batch), 0) FROM {$this->table}")->fetchColumn() + 1;
}

private function getLastBatch(): int
{
return (int)$this->pdo->query("SELECT COALESCE(MAX(batch), 0) FROM {$this->table}")->fetchColumn();
}

private function getBatchMigrations(int $batch): array
{
$stmt = $this->pdo->prepare("SELECT migration FROM {$this->table} WHERE batch = ? ORDER BY id ASC");
$stmt->execute([$batch]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}

private function loadMigration(string $file): Migration
{
require_once $this->migrationDir . '/' . $file;
$className = pathinfo($file, PATHINFO_FILENAME);
$className = $this->formatClassName($className);
return new $className($this->pdo);
}

private function formatClassName(string $name): string
{
preg_match('/^\d{4}_\d{2}_\d{2}_\d{6}_(.+)$/', $name, $matches);
if (isset($matches[1])) {
return implode('', array_map('ucfirst', explode('_', $matches[1])));
}
return $name;
}

private function record(string $file, int $batch): void
{
$this->pdo->prepare("INSERT INTO {$this->table} (migration, batch) VALUES (?, ?)")->execute([$file, $batch]);
}

private function remove(string $file): void
{
$this->pdo->prepare("DELETE FROM {$this->table} WHERE migration = ?")->execute([$file]);
}
}
?>

迁移文件示例。

```php
// 2024_01_01_000001_create_users_table.php
class CreateUsersTable extends Migration
{
public function up(): void
{
$this->pdo->exec("
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
");
}

public function down(): void
{
$this->pdo->exec("DROP TABLE IF EXISTS users");
}
}
?>
```

迁移系统的核心是记录已执行的迁移,确保每个迁移只执行一次。回滚功能可以撤销之前的变更。团队协作时,按顺序执行迁移保持数据库结构一致。

http://www.jsqmd.com/news/968135/

相关文章:

  • 3步快速掌握AcFunDown:A站视频本地化终极指南
  • PotPlayer百度翻译插件:5分钟实现免费字幕实时翻译的终极指南
  • 美新半导体单芯片MEMS-CMOS融合技术:热式加速度传感器的创新与突破
  • 技术战略转向:从防御到进攻的研发思维与工具革命
  • 宣城市2026年上门黄金回收白银回收铂金回收测评,五家全城可上门实体店整理 - 干豆腐啊
  • ADHD尿液代谢组学诊断:机器学习与生物标志物研究
  • 2026榆林黄金回收白银回收铂金回收怎么变现?实地探访 5 家本地老牌回收店铺 - 中安检金银铂钻回收
  • 硬件工程师实战指南:从接口到PCB的ESD系统防护设计
  • 51单片机驱动Nokia 5110液晶屏:从硬件电路到图形显示全解析
  • 电信垄断背后的技术经济学:工程师视角下的创新空间与产业逻辑
  • 2026湛江黄金回收白银回收铂金回收怎么变现?实地探访 5 家本地老牌回收店铺 - 中安检金银铂钻回收
  • 不开通会员也能用CSDN AI发文?揭秘4步绕过订阅墙的合规操作流程(官方接口调用实录)
  • Altera Quartus浮动许可服务器部署实战:从原理到避坑指南
  • 永州黄金回收白银回收铂金回收哪家靠谱?2026 实地测评 5 家高人气实体门店 - 信誉隆金银铂奢回收
  • 别急着删缓存!遇到conda的InvalidArchiveError,先试试这三步排查法(附conda clean详解)
  • 开箱即用的全球七大洲边界矢量文件(含WGS84坐标系与ArcGIS/QGIS图层样式)
  • Sunshine游戏串流:如何用开源技术构建个人云游戏服务器?
  • 上海市2026年上门黄金回收白银回收铂金回收测评,五家全城可上门实体店整理 - 干豆腐啊
  • Windows更新卡住怎么办?终极修复工具Reset Windows Update Tool完全指南
  • 音频接口核心解析:Line in与Mic in的电平、阻抗与电路设计差异
  • 51单片机驱动数码管:MAX7219芯片原理、驱动代码与电路设计详解
  • 上饶市2026年上门黄金回收白银回收铂金回收测评,五家全城可上门实体店整理 - 干豆腐啊
  • Python+Django实战:构建企业级房屋租赁管理系统(房源/租客/合同/租金/报修/统计)
  • 延安黄金回收白银回收铂金回收去哪卖?5 家实地探访靠谱门店汇总 2026 - 中业金奢再生回收中心
  • 宜宾市2026年上门黄金回收白银回收铂金回收测评,五家全城可上门实体店整理 - 干豆腐啊
  • SAR回波成像对比实验包:含RCMC校正与无校正的RDA算法三脚本实现
  • 三线与四线PWM风扇拆解:从电路原理到选型实战
  • 硬件创业启示录:从知识产权到供应链管理的实战复盘
  • 从华强北到全球供应链:芯片分销的江湖、角色与工程师协作指南
  • 从木兰事件看技术研发:制度、人性与工程真实性的反思