本文目录导读:

我来详细介绍PHP项目实现数据迁移工具的几种主流方案和实践方法。
使用成熟的数据迁移库
Phinx (推荐)
最流行的PHP数据迁移库,支持多种数据库。
// 安装
composer require robmorgan/phinx
// 创建迁移文件
vendor/bin/phinx create MyNewMigration
// 示例迁移文件
<?php
use Phinx\Migration\AbstractMigration;
class CreateUsersTable extends AbstractMigration
{
public function up()
{
$table = $this->table('users', ['id' => false, 'primary_key' => ['id']]);
$table->addColumn('id', 'integer', ['signed' => false, 'identity' => true])
->addColumn('username', 'string', ['limit' => 100])
->addColumn('email', 'string')
->addColumn('password', 'string')
->addColumn('created_at', 'datetime')
->addColumn('updated_at', 'datetime')
->create();
}
public function down()
{
$this->dropTable('users');
}
}
Laravel Migration (Laravel框架)
// Laravel框架内置
php artisan make:migration create_users_table
// 示例
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
手动实现轻量级迁移工具
<?php
class SimpleMigration
{
private $pdo;
private $migrationsPath;
private $migrationsTable = 'migrations';
public function __construct(PDO $pdo, string $migrationsPath)
{
$this->pdo = $pdo;
$this->migrationsPath = $migrationsPath;
}
public function initialize()
{
// 创建迁移记录表
$this->pdo->exec("
CREATE TABLE IF NOT EXISTS {$this->migrationsTable} (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
batch INT NOT NULL,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
");
}
public function migrate()
{
$this->initialize();
// 获取已执行的迁移
$executed = $this->getExecutedMigrations();
$batch = $this->getNextBatchNumber();
// 获取所有迁移文件
$files = glob($this->migrationsPath . '/*.php');
sort($files);
foreach ($files as $file) {
$migrationName = basename($file, '.php');
if (!in_array($migrationName, $executed)) {
// 执行迁移
require_once $file;
$className = $this->getClassName($migrationName);
$migration = new $className($this->pdo);
echo "Running migration: {$migrationName}\n";
$migration->up();
// 记录执行状态
$stmt = $this->pdo->prepare(
"INSERT INTO {$this->migrationsTable} (migration, batch) VALUES (?, ?)"
);
$stmt->execute([$migrationName, $batch]);
}
}
}
public function rollback()
{
// 获取最后一批迁移
$stmt = $this->pdo->prepare(
"SELECT migration FROM {$this->migrationsTable} WHERE batch = (
SELECT MAX(batch) FROM {$this->migrationsTable}
) ORDER BY id DESC"
);
$stmt->execute();
$lastBatch = $stmt->fetchAll(PDO::FETCH_COLUMN);
foreach ($lastBatch as $migrationName) {
require_once $this->migrationsPath . '/' . $migrationName . '.php';
$className = $this->getClassName($migrationName);
$migration = new $className($this->pdo);
echo "Rolling back: {$migrationName}\n";
$migration->down();
// 删除记录
$this->pdo->prepare(
"DELETE FROM {$this->migrationsTable} WHERE migration = ?"
)->execute([$migrationName]);
}
}
private function getExecutedMigrations(): array
{
$stmt = $this->pdo->query(
"SELECT migration FROM {$this->migrationsTable} ORDER BY id ASC"
);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
private function getNextBatchNumber(): int
{
$stmt = $this->pdo->query(
"SELECT COALESCE(MAX(batch), 0) + 1 FROM {$this->migrationsTable}"
);
return (int) $stmt->fetchColumn();
}
private function getClassName(string $migrationName): string
{
// 移除时间戳,转换为类名
$parts = preg_split('/_/', $migrationName, 2);
return 'Migration_' . str_replace(' ', '', ucwords(str_replace('_', ' ', $parts[1] ?? $parts[0])));
}
}
// 使用示例
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'password');
$migration = new SimpleMigration($pdo, __DIR__ . '/migrations');
// 执行迁移
$migration->migrate();
// 回滚
// $migration->rollback();
} catch (PDOException $e) {
echo "Database error: " . $e->getMessage() . "\n";
}
迁移文件示例
<?php
// migrations/20210101000001_create_users_table.php
class Migration_CreateUsersTable
{
private $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function up()
{
$this->pdo->exec("
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
");
}
public function down()
{
$this->pdo->exec("DROP TABLE IF EXISTS users");
}
}
数据库种子数据功能
<?php
// seeds/AdminUserSeeder.php
class AdminUserSeeder
{
private $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function run()
{
$stmt = $this->pdo->prepare("
INSERT INTO users (username, email, password, role)
VALUES (?, ?, ?, ?)
");
$stmt->execute([
'admin',
'admin@example.com',
password_hash('admin123', PASSWORD_BCRYPT),
'admin'
]);
echo "Admin user created successfully\n";
}
}
命令行工具封装
<?php
// migrate.php - 命令行入口
require_once 'vendor/autoload.php';
// 配置
$config = [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'test',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8mb4',
'migrations_path' => __DIR__ . '/migrations',
'seeds_path' => __DIR__ . '/seeds'
];
// 参数处理
$command = $argv[1] ?? 'help';
$pdo = new PDO(
"{$config['driver']}:host={$config['host']};dbname={$config['database']};charset={$config['charset']}",
$config['username'],
$config['password']
);
$migration = new SimpleMigration($pdo, $config['migrations_path']);
switch ($command) {
case 'migrate':
$migration->migrate();
break;
case 'rollback':
$migration->rollback();
break;
case 'seed':
// 运行种子数据
$seederFile = $config['seeds_path'] . '/' . ($argv[2] ?? '') . '.php';
if (file_exists($seederFile)) {
require_once $seederFile;
$seeder = new AdminUserSeeder($pdo);
$seeder->run();
}
break;
default:
echo "Usage: php migrate.php [migrate|rollback|seed]\n";
}
最佳实践建议
版本控制
// 迁移文件命名规范
// YYYYMMDDHHMMSS_description.php
// 20231201120000_create_users_table.php
// 确保按时间顺序执行
function sortMigrations($files) {
sort($files);
return $files;
}
事务处理
// 使用事务确保数据一致性
public function migrate()
{
try {
$this->pdo->beginTransaction();
// 执行迁移操作
$this->pdo->exec("ALTER TABLE users ADD COLUMN phone VARCHAR(20)");
$this->pdo->commit();
} catch (Exception $e) {
$this->pdo->rollBack();
throw $e;
}
}
安全考虑
// 验证迁移文件来源
function validateMigration($file) {
// 检查文件格式
if (!preg_match('/^\d{14}_.+\.php$/', basename($file))) {
throw new Exception("Invalid migration filename: " . $file);
}
// 检查文件是否可读
if (!is_readable($file)) {
throw new Exception("Migration file not readable: " . $file);
}
}
推荐使用 Phinx 或 Laravel Migration 等成熟方案,它们提供了更完善的功能和更好的安全性,如果项目较小或需要自定义迁移逻辑,可以参考上述轻量级实现方案,记住始终在开发环境中测试迁移,并在生产环境中做好备份。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播