PHP 无痛迁移方案
分层迁移策略
渐进式迁移(Strangler Pattern)
// 旧代码
class OldOrderService {
public function process($order) {
// 旧逻辑
}
}
// 新代码
class NewOrderService {
public function process($order) {
// 新逻辑
}
}
// 路由适配器
class OrderServiceAdapter {
private $oldService;
private $newService;
private $featureFlag;
public function process($order) {
if ($this->featureFlag->isEnabled('new_order_service')) {
return $this->newService->process($order);
}
return $this->oldService->process($order);
}
}
环境隔离策略
// config/migration.php
return [
'current_version' => 'v1',
'target_version' => 'v2',
'environments' => [
'development' => [
'source' => 'php5.6',
'target' => 'php8.2'
],
'staging' => [
'source' => 'php7.4',
'target' => 'php8.2'
],
'production' => [
'source' => 'php7.4',
'target' => 'php8.2',
'rollback_enabled' => true
]
]
];
代码兼容性处理
Deprecated 函数兼容层
// compat/functions.php
if (!function_exists('each')) {
function each(&$array) {
$key = key($array);
$result = ($key === null) ? false : [$key, current($array), 'key' => $key, 'value' => current($array)];
next($array);
return $result;
}
}
// 旧的 mysql_* 函数模拟
if (!function_exists('mysql_connect')) {
function mysql_connect($host, $user, $pass) {
return new mysqli($host, $user, $pass);
}
}
类型转换处理
// 自动类型转换适配器
class TypeAdapter {
public static function adaptValue($value, $oldType, $newType) {
switch ("$oldType:$newType") {
case 'string:int':
return (int) $value;
case 'int:string':
return (string) $value;
case 'null:empty':
return $value ?? '';
default:
return $value;
}
}
}
数据库迁移方案
平滑数据库迁移
class DatabaseMigration {
private $schemaVersion = 'schema_version';
public function migrate() {
$current = $this->getCurrentVersion();
$target = $this->getTargetVersion();
while ($current < $target) {
$migrationClass = "Migration_v{$current}_to_" . ($current + 1);
if (class_exists($migrationClass)) {
$migration = new $migrationClass();
$migration->up();
$current++;
$this->updateVersion($current);
}
}
}
// 双写策略
public function dualWrite($data) {
$oldDb = DB::connection('old');
$newDb = DB::connection('new');
$oldDb->table('orders')->insert($data);
$newDb->table('orders')->insert($data);
if ($newDb->getLastInsertId() != $oldDb->getLastInsertId()) {
$this->rollback($oldDb, $newDb);
}
}
}
数据同步脚本
#!/bin/bash # sync_data.sh # 全量同步 php artisan migrate:sync --full # 增量同步(实时) php artisan migrate:sync --incremental --from="2023-01-01" # 验证数据一致性 php artisan migrate:verify --tables=users,orders
运行环境兼容
多版本 PHP 共存
# nginx.conf - 按路径分发
location ~ ^/api/v1/ {
fastcgi_pass php74.sock;
}
location ~ ^/api/v2/ {
fastcgi_pass php82.sock;
}
Docker 多阶段迁移
# Dockerfile
FROM php:8.2-fpm AS php82
# 新版本环境
FROM php:7.4-fpm AS php74
# 旧版本环境
# 动态切换
ARG PHP_VERSION=7.4
FROM php:${PHP_VERSION}-fpm
自动化迁移工具
PHP-CS-Fixer 自动修复
# 自动修复代码风格和废弃语法
php-cs-fixer fix /path/to/project \
--rules=@PHP74Migration,@PHP80Migration \
--diff \
--dry-run # 先预览改动
php-cs-fixer fix /path/to/project \
--rules=@PHP74Migration,@PHP80Migration \
--allow-risky=yes
Rector 自动化重构
// rector.php
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/app',
__DIR__ . '/src'
]);
$rectorConfig->sets([
SetList::CODE_QUALITY,
SetList::PHP_70, SetList::PHP_71,
SetList::PHP_72, SetList::PHP_73,
SetList::PHP_74, SetList::PHP_80,
SetList::PHP_81, SetList::PHP_82
]);
$rectorConfig->skip([
// 跳过不需要处理的文件
'*/vendor/*',
'*/storage/*'
]);
};
// 执行
vendor/bin/rector process --dry-run # 预览
vendor/bin/rector process # 执行
监控与回滚机制
金丝雀发布
class CanaryRelease {
private $releaseRatio = 10; // 10% 流量
public function shouldUseNewVersion() {
$random = random_int(1, 100);
return $random <= $this->releaseRatio;
}
public function monitor($requestId, $responseTime, $errorRate) {
Log::channel('canary')->info('Canary metrics', [
'request_id' => $requestId,
'response_time' => $responseTime,
'error_rate' => $errorRate,
'version' => $this->getCurrentVersion()
]);
}
public function rollback($reason) {
// 自动回滚
$this->releaseRatio = 0;
event('canary.rollback', $reason);
}
}
全链路监控
class MigrationMonitor {
public function track($operation, $duration, $success) {
$metrics = [
'timestamp' => now(),
'operation' => $operation,
'duration' => $duration,
'success' => $success,
'environment' => app()->environment(),
'php_version' => PHP_VERSION
];
// 发送到监控系统
StatsD::increment("migration.{$operation}." . ($success ? 'success' : 'failed'));
if (!$success) {
Alert::send('Migration failed: ' . $operation);
}
}
}
自动回滚机制
class AutoRollback {
private $threshold = [
'error_rate' => 5, // 5% 错误率
'response_time' => 2, // 2秒响应时间
'memory_usage' => 80 // 80%内存使用
];
public function checkAndRollback() {
$metrics = $this->collectMetrics();
if ($metrics['error_rate'] > $this->threshold['error_rate']) {
$this->rollback('High error rate');
}
if ($metrics['response_time'] > $this->threshold['response_time']) {
$this->rollback('Slow response');
}
}
private function rollback($reason) {
// 回滚到上一个版本
exec('php artisan migrate:rollback');
event('system.rollback', ['reason' => $reason]);
}
}
测试策略
兼容性测试矩阵
class CompatibilityTest extends PHPUnit\Framework\TestCase {
/**
* @dataProvider phpVersionsProvider
*/
public function testApplicationWorksOnPHPVersions($phpVersion) {
// 在不同 PHP 版本下运行测试
$result = $this->runTests($phpVersion);
$this->assertTrue($result['passed']);
}
public function phpVersionsProvider() {
return [
'php-7.4' => ['7.4'],
'php-8.0' => ['8.0'],
'php-8.1' => ['8.1'],
'php-8.2' => ['8.2']
];
}
}
A/B 对比测试
class ABTesting {
public function compare($oldFunction, $newFunction, $testCases) {
$results = ['old' => [], 'new' => []];
foreach ($testCases as $testCase) {
$results['old'][] = $oldFunction($testCase);
$results['new'][] = $newFunction($testCase);
// 对比结果一致性
if ($results['old'] != $results['new']) {
$this->logDiscrepancy($testCase, $results['old'], $results['new']);
}
}
return $results;
}
}
迁移检查清单
✅ 迁移前检查
- [ ] 代码风格检查通过
- [ ] 单元测试覆盖率达到要求
- [ ] 依赖包版本兼容
- [ ] 数据库备份完成
- [ ] 回滚方案准备就绪
📝 执行迁移
- [ ] 先迁移开发环境
- [ ] 验证功能完整性
- [ ] 迁移测试环境
- [ ] 执行性能测试
- [ ] 部署到生产环境(低流量时段)
🔄 迁移后监控
- [ ] 错误日志监控
- [ ] 性能指标对比
- [ ] 用户反馈收集
- [ ] 持续优化调整
通过以上方案,可以实现 PHP 版本的无痛迁移,最小化业务影响,并提供完善的回滚机制保障安全,每一步都有明确的适配策略和验证方法,确保迁移过程平稳有序。
