本文目录导读:

针对PHP项目的版本管理与回滚,以下是几种主流的实践方案,涵盖从简单到专业的场景。
版本控制系统(Git)基础
Git分支策略
# 主分支 main / master # 生产环境 develop # 开发环境 # 功能分支 feature/* # 新功能开发 bugfix/* # Bug修复 release/* # 发布准备 # 热修复分支 hotfix/* # 紧急修复
版本标记
# 语义化版本标记 git tag v1.0.0 git tag v1.1.0-beta git tag v2.0.0-rc1 # 推送到远程 git push origin --tags
部署策略
1 手动备份回滚(简单项目)
# 部署脚本示例
#!/bin/bash
PROJECT_DIR="/var/www/myapp"
BACKUP_DIR="/var/backups/myapp"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 创建备份
tar -czf "${BACKUP_DIR}/backup_${TIMESTAMP}.tar.gz" -C "${PROJECT_DIR}" .
# 部署新版本
cd ${PROJECT_DIR}
git pull origin main
# 回滚操作
rollback() {
local backup_file=$1
if [ -f "$backup_file" ]; then
rm -rf ${PROJECT_DIR}/*
tar -xzf "$backup_file" -C ${PROJECT_DIR}
echo "回滚完成: $backup_file"
fi
}
2 符号链接切换(推荐)
// 项目目录结构 /var/www/ ├── releases/ │ ├── 20240101_100000/ # v1.0.0 │ ├── 20240115_143000/ # v1.1.0 │ └── 20240201_090000/ # v1.2.0 ├── shared/ # 共享资源 │ ├── .env │ ├── storage/ │ └── uploads/ └── current -> releases/20240201_090000/ # 当前版本符号链接
部署脚本
#!/bin/bash
RELEASES_DIR="/var/www/releases"
SHARED_DIR="/var/www/shared"
CURRENT_LINK="/var/www/current"
deploy() {
# 1. 创建新版本目录
RELEASE_DIR="${RELEASES_DIR}/$(date +%Y%m%d_%H%M%S)"
mkdir -p $RELEASE_DIR
# 2. 克隆代码
git clone -b main git@github.com:user/repo.git $RELEASE_DIR
# 3. 安装依赖
cd $RELEASE_DIR
composer install --no-dev --optimize-autoloader
# 4. 设置共享资源链接
ln -nfs $SHARED_DIR/.env $RELEASE_DIR/.env
ln -nfs $SHARED_DIR/storage $RELEASE_DIR/storage
# 5. 切换符号链接
ln -nfs $RELEASE_DIR $CURRENT_LINK
# 6. 执行迁移
cd $CURRENT_LINK
php artisan migrate --force
}
rollback() {
# 回滚到上一个版本
PREVIOUS_RELEASE=$(ls -t $RELEASES_DIR | head -n 2 | tail -n 1)
ln -nfs "${RELEASES_DIR}/${PREVIOUS_RELEASE}" $CURRENT_LINK
# 如果有数据库迁移,需要回滚
cd $CURRENT_LINK
php artisan migrate:rollback
}
数据库回滚策略
Laravel Migration
// 创建迁移 php artisan make:migration add_price_to_products // 执行迁移 php artisan migrate // 回滚 php artisan migrate:rollback php artisan migrate:reset php artisan migrate:refresh // 回滚并重新迁移
手动数据库备份
-- 备份脚本 mysqldump -u root -p mydatabase > backup_20240101.sql -- 恢复 mysql -u root -p mydatabase < backup_20240101.sql
自动化部署工具
1 Deployer(PHP官方推荐)
// deploy.php
namespace Deployer;
require 'recipe/laravel.php';
// 项目配置
set('application', 'my_app');
set('repository', 'git@github.com:user/repo.git');
set('php_version', '8.1');
// 服务器配置
host('production')
->setHostname('example.com')
->set('remote_user', 'deploy')
->set('deploy_path', '/var/www/myapp');
// 任务
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:vendors',
'deploy:writable',
'artisan:storage:link',
'artisan:view:cache',
'artisan:config:cache',
'artisan:migrate',
'deploy:symlink',
'deploy:unlock',
'cleanup',
]);
// 回滚
task('rollback', function () {
$releases = get('releases_list');
if (isset($releases[1])) {
$rollbackRelease = $releases[1];
run("cd {{deploy_path}} && {{bin/symlink}} -f releases/{$rollbackRelease} current");
run("cd {{deploy_path}} && rm -rf releases/{$releases[0]}");
writeln("Rolled back to {$rollbackRelease}");
}
});
2 Capistrano
# Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/composer'
require 'capistrano/file-permissions'
# config/deploy.rb
set :application, 'my_app'
set :repo_url, 'git@github.com:user/repo.git'
set :deploy_to, '/var/www/myapp'
set :keep_releases, 5
namespace :deploy do
after :updated, 'composer:install'
after :published, :restart
desc 'Rollback to previous release'
task :rollback do
on roles(:app) do
execute "cd #{deploy_to} && ls -t releases | head -n 2 | tail -n 1"
end
end
end
CI/CD 集成
GitHub Actions
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
- name: Deploy to Server
uses: deployphp/action@v1
with:
dep: deploy production
private-key: ${{ secrets.SSH_PRIVATE_KEY }}
最佳实践
1 版本号管理
- 使用语义化版本(SemVer):主版本.次版本.修订号
- 在
composer.json中记录版本
2 变更日志
# CHANGELOG.md ## [1.2.0] - 2024-01-15 ### Added - New payment gateway integration - User notification system ### Changed - Updated dependencies - Improved performance ### Fixed - Login session timeout issue - Database connection pool exhaustion ## [1.1.0] - 2024-01-01 ### Added - Product search functionality
3 健康检查
// health.php
<?php
// 部署后验证
$checks = [
'database' => function() {
try {
DB::connection()->getPdo();
return true;
} catch (\Exception $e) {
return false;
}
},
'cache' => function() {
return Cache::store('redis')->set('health_check', time());
},
'queue' => function() {
return Queue::size() < 1000; // 队列长度检查
}
];
foreach ($checks as $name => $check) {
if (!$check()) {
// 触发回滚
exec('php artisan deploy:rollback');
die("Health check failed: {$name}");
}
}
4 回滚策略决策树
是否影响数据库?
├── 是
│ ├── 是否可逆迁移?
│ │ ├── 是 → 执行 migrate:rollback
│ │ └── 否 → 手动修复数据库 + 代码回滚
│ └── 否 → 直接回滚代码
└── 否 → 直接回滚代码
是否影响缓存/队列?
├── 是 → 清理相关缓存/队列
└── 否 → 无需处理
常见问题处理
1 紧急回滚脚本
#!/bin/bash
# emergency-rollback.sh
RELEASES_DIR="/var/www/releases"
CURRENT_LINK="/var/www/current"
# 自动检测问题版本
CURRENT_RELEASE=$(readlink -f $CURRENT_LINK)
CURRENT_RELEASE_NAME=$(basename $CURRENT_RELEASE)
# 获取上一个版本
PREVIOUS_RELEASE=$(ls -t $RELEASES_DIR | grep -v "^$CURRENT_RELEASE_NAME$" | head -n 1)
if [ -n "$PREVIOUS_RELEASE" ]; then
# 切换符号链接
ln -nfs "${RELEASES_DIR}/${PREVIOUS_RELEASE}" $CURRENT_LINK
# 数据库回滚
cd $CURRENT_LINK
php artisan down
php artisan migrate:rollback
php artisan up
echo "紧急回滚完成: $CURRENT_RELEASE_NAME → $PREVIOUS_RELEASE"
else
echo "错误: 没有可用的回滚版本"
exit 1
fi
通过这些方案,你可以根据项目规模和团队需求选择合适的版本管理和回滚策略,建议从小规模开始,逐步完善自动化流程。