1. 项目背景:当PHP老项目成为"技术债重灾区"
接手这个项目的第一天,我就意识到问题的严重性。这个运行了8年的电商系统,代码库体积达到12GB,核心业务逻辑分散在47个文件中,最老的代码可以追溯到PHP 5.3时代。系统每天处理着超过200万的订单,但代码质量却让人触目惊心:
- 单个控制器文件平均3000+行代码
- 全局函数多达287个,相互调用关系复杂
- 数据库查询直接写在视图层
- 同一业务逻辑平均有3.8种实现方式
最典型的例子是订单状态判断函数:
php复制function checkOrderStatus($order) {
if (isset($order['status_code'])) {
return $order['status_code'] == 1
|| $order['status'] == 'active'
|| $order['is_valid'];
}
return false;
}
这个函数在系统中被调用了89次,返回值的类型和含义完全取决于传入数据的结构。这种代码就像定时炸弹,任何改动都可能引发连锁反应。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 重构原则:外科手术式的渐进改造
面对这样的系统,传统的"推倒重来"方案根本不现实。经过评估,我制定了三条核心原则:
- 保持系统持续可用:任何时候都不能影响线上业务
- 小步快跑:每次改动控制在2小时内可回滚的范围
- 先加固再改造:建立安全网后再进行实质性重构
2.1 建立监控体系:给系统装上"心电图"
重构的第一步不是写代码,而是建立监控。我在关键节点部署了三种日志:
- 性能日志:记录每个接口的响应时间、SQL查询次数
php复制$start = microtime(true);
// 业务逻辑
$elapsed = round((microtime(true) - $start) * 1000, 2);
Logger::debug('API_PERF', [
'endpoint' => $_SERVER['REQUEST_URI'],
'time' => $elapsed.'ms'
]);
- 异常日志:捕获所有未被处理的异常
php复制set_exception_handler(function($e) {
Logger::error('UNCAUGHT_EXCEPTION', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
});
- 业务日志:记录核心业务状态变更
php复制function updateOrderStatus($orderId, $newStatus) {
$oldStatus = getOrderStatus($orderId);
Logger::info('ORDER_STATUS_CHANGE', [
'order_id' => $orderId,
'from' => $oldStatus,
'to' => $newStatus,
'operator' => getCurrentUserId()
]);
// 实际更新逻辑
}
这套日志系统运行两周后,我们发现了三个严重问题:
- 某个定时任务存在内存泄漏,运行3天后会耗尽服务器内存
- 支付回调接口平均响应时间达2.3秒
- 有17%的订单状态变更没有正确记录
3. 代码改造:从止血到新生
3.1 消灭"魔法值":用枚举建立业务字典
老系统中充斥着各种神秘的数字和字符串:
php复制if ($order['status'] == 5) {
// 谁知道5代表什么?
}
我创建了业务枚举类,逐步替换这些魔法值:
php复制enum OrderStatu
