接到一个别人的 ThinkPHP 项目,最怕的不是代码烂,是不知道哪里被动过。上一任开发者可能改过核心文件、删过迁移脚本、把调试开关留在线上,甚至留了个后门。这篇是我接手老项目时的固定动作,按顺序走一遍,能避开 90% 的「改一处崩三处」。
为什么不能上来就改需求
甲方第一句话通常是「帮我把这个功能改一下」。但老项目的真实状态是:你看到的页面能用,不代表底层是正常的。很多项目是靠打补丁撑着的,你改的那处正好压在一堆补丁上面。
所以我接手任何老项目,第一件事都不是写代码,而是先把现状摸清楚,并且让它能在本地跑起来。跑不起来的项目,谈需求没有意义。
1. 先确认版本:TP5 和 TP6 完全是两套东西
ThinkPHP 5.0、5.1、6.x 之间差异很大,控制器写法、门面类、中间件、配置读取方式都不同。看 composer.json 里的版本约束最准:
cat composer.json | grep -A2 '"require"'同时确认 PHP 版本。TP6 要求 PHP 7.2+,TP8 要求 8.0+。如果项目是 TP5.0 跑在 PHP 7.4 上,很多老语法会直接报错或埋着警告——升级 PHP 版本前必须先在测试环境跑一遍,别直接在生产环境动。
2. 配置和环境:调试开关是最危险的一项
看 .env 和 config/database.php:
APP_DEBUG必须是false。线上开着 debug,报错页会把数据库账号、目录结构、完整 SQL 全打出来,等于把门钥匙贴在门上- 数据库配置是否指向正式库,有没有硬编码的测试库地址
runtime目录权限,缓存和日志写不进去会直接白屏- 有没有
config目录下的环境配置混用(config/production/之类)
我见过最常见的事故是:本地开发时 debug 开着,打包上传时忘了关,上线后被搜索引擎扫到报错页,数据库信息直接暴露。
3. 目录里有没有不该有的东西
老项目跑了一两年,public、runtime、uploads 里常常堆着测试文件、备份文件、甚至后门。查这几类:
find . -name "*.php" -newermt "-30 days" -not -path "./vendor/*"
find . -name "*.bak" -o -name "*.sql" -o -name "*.zip" -o -name "*.rar"重点看:public 下有没有随机命名的 php 文件、.env.bak 这类备份是否能被直接访问、上传目录是否允许执行 PHP。一个正常的 TP 项目,public 下只应该有 index.php、静态资源和上传目录。
4. 路由和伪静态:TP 项目一半的 404 来自这里
ThinkPHP 默认用 pathinfo。Nginx 下没配伪静态,访问 /admin/index/index 会 404,看起来像「项目坏了」,其实只是 rewrite 没写。
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}
}排查顺序固定:先确认 /index.php?s=/admin/index/index 能不能开,能开就是伪静态问题,不能开才是代码问题。这个判断能省掉大量瞎猜。
5. 数据库和代码对不对得上
老项目最隐蔽的坑:代码里读的字段,表里根本没有;或者表里有一堆废弃字段,没人知道干嘛用的。
做法是把核心表的字段导出来,对照模型里的 $field、查询条件、前端表单逐项看一遍。重点看有没有软删除字段(delete_time)、状态字段(status 的取值含义)、关联外键。这三类理解错了,写出来的功能一定是错的。
SHOW FULL COLUMNS FROM 表名;6. 依赖完整不完整
看 vendor 目录在不在、composer.lock 有没有提交。有些项目是把 vendor 一起打包上传的,那就得确认里面的包版本和 composer.json 一致。缺依赖的项目,跑起来会报一堆 Class not found,很容易误判成代码坏了。
7. 先备份,再动手
这一步没有例外。接手第一天就做一次完整备份,包括代码和数据库,存到项目目录之外:
tar -czf ../backup-site-$(date +%F).tar.gz .
mysqldump -u 用户 -p 库名 > ../backup-db-$(date +%F).sql后面每次改动前再备份一次对应的文件。没有备份的老项目,改坏了就是灾难——因为你连「原来是什么样」都不知道。
接手检查清单
| 检查项 | 看什么 | 常见问题 |
|---|---|---|
| 框架版本 | composer.json | TP5 和 TP6 语法混用 |
| PHP 版本 | php -v | 版本低于框架要求,升级即崩 |
| 调试开关 | .env 的 APP_DEBUG | 线上开着,泄露数据库信息 |
| 目录残留 | public、runtime | 测试文件、备份、后门 |
| 伪静态 | Nginx / Apache 配置 | 全站 404 被误判为代码问题 |
| 表结构 | SHOW FULL COLUMNS | 字段含义靠猜,功能写错 |
| 依赖 | vendor、composer.lock | 缺包,报 Class not found |
| 备份 | 代码 + 数据库 | 没备份就动手 |
关于「改个功能」这件事
检查完这七项,通常才具备谈需求的条件。因为这时候你能回答甲方三个问题:这个功能改动会影响哪些地方、大概要多久、有没有风险。
反面情况是:上来就改,改完发现另一个模块跟着坏了,然后再修,越修越乱。老项目的时间成本不在写代码,在搞清楚代码。这也是为什么同样的功能,在新项目里一天能做完,在老项目里可能要三天——不是能力问题,是项目本身的复杂度。
如果你手上有个跑了几年的 PHP 系统,改一处崩一处,或者原来的开发者联系不上了,可以把项目情况和具体需求说清楚,我先判断能不能接、要多久。ThinkPHP 5 / 6 和原生 PHP 的项目都处理过。
相关:PHP 功能开发、二次开发和后台模块的计价方式写在 服务与报价 页。
本文由 admin 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。