本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!
背景
刚进公司不久,我接手了一个老项目,看到项目代码,我崩溃了,php5.3,程序和数据库都是gbk编码,手写的orm操作,开发了一段时间之后,让我别扭的地方主要有以下几点:
1、框架和很多组件都是以前的开发自己封装的,没有使用文档。
2、程序和数据库都是gbk编码,运营的同事时不时的过来问,我刚才填的东西怎么又乱码了… …
3、php版本低,很多高版本的方法用不了,没有自动加载,许多新的组件包引入不了,并且稳定的最新包都要求php7以上版本。
4、项目经手的开发人员太多,业务逻辑复杂,很多无用的代码没有删除,有很明显为了完成某个小功能简单修补的痕迹。
与技术负责人和产品经理讨论之后,因为这个项目后面调整的地方比较多并且要长期维护的,所以为了项目更好的发展,还是决定重构一下。
这里还是要说明一下,重构并不是说之前的项目很糟糕,相反经过这么多年的产品迭代,这么多人员的开发,还能稳定的运行和开发,说明架构还是可以的,我也从里面许多开发人员自己封装的功能中学到了很多。
重构流程
1、服务器上再配一个高版本的PHP,我配置的是php7.3。
2、框架选择的是Yii2(也可以选择其他框架,自己使用方便就好),配置好数据库、redis及其他第三方库的连接,与老项目保持一致。
3、与产品确定要重构的第一个url地址,在新框架里重写该地址的代码。
4、服务器nginx配置上面url地址的重定向。
5、长时间重复3、4步操作,直到重构完大部分核心页面(到现在我也没重构完,因为有些页面功能简单,而且以后改动几率极低)。
6、与运维一起把数据库编码全部改成utf-8,线上操作前还是要反复在测试服务器上转码测试,确保不会出现乱码的问题。
注:其实更改数据库编码与重构项目代码没有先后顺序,不同编码的程序数据库连接时指定好对应的编码就行了,另外要提醒的是,该操作要根据实际情况,如果数据在不断的实时更新,数据准确性要求比较高,还是建议不要操作,挺危险的。
Nginx配置和PHP多版本共存
由于这个项目是个很老的项目,框架也是之前的开发自己写的,美化url的方法是用了nginx的rewrite模块来实现url的重写,nginx配置大致是这样的:
server {
listen 80;
server_name www.test.com;
# 老项目的代码目录
root /var/www/test.com;
index index.php index.html index.htm;
location / {
# 大致意思就是 找post控制器里的detail方法,并把id参数传过去
rewrite "^/post/(\d{1,6}).html$" /server/index.php?con=post&ac=detail&id=$1 last;
# 意思基本同上
rewrite "^/article/(\d{1,6}).html$" /server/index.php?con=article&ac=detail&id=$1 last;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_pass unix:/var/run/php/php5.3-fpm.sock;
}
}
复制代码
如果不做url的美化,上面想访问详情页url地址是:
http://www.test.com/server/index.php?con=post&ac=detail&id=123
http://www.test.com/server/index.php?con=article&ac=detail&id=123
复制代码
nginx把url地址重写后,访问详情页就变成了:
http://www.test.com/post/123.html
http://www.test.com/article/123.html
复制代码
很显然第二种url地址,用户看起来更顺眼,但写成第二种方式显然不是为了让用户看着顺眼,而是第二种方式搜索引擎更喜欢,更容易帮我们引流。
现在的框架比如laravel或者yii2框架都是自带url重写功能,所以上面那种nginx配置已经很难见到了。其他的就不多说了,看如何更改上面的nginx配置。
通过观察上面的nginx配置可以发现,如果我们想要在url地址不变的情况下,用新框架重写单个url地址的代码,只需要把rewrite后面的指向更改一下就行,例如
# 更改后的地址
rewrite "^/post/(\d{1,6}).html$" /index.php?r=post/detail&id=$1 last;
# 没更改的地址
rewrite "^/article/(\d{1,6}).html$" /server/index.php?con=article&ac=detail&id=$1 last;
复制代码
更改完问题来了,新老代码是两个项目,有两个问题:
- 怎么让第一个地址访问新项目的代码,让第二个访问老项目的代码
- 新项目代码是用的php7.3,老项目用的是php5.3,怎么让它根据项目自动选择php版本
通过观察nginx配置我们发现,最下面那个location是用了正则匹配的,匹配地址中有”.php”默认用PHP去解析,所以我们只需要再加一个正则,新老项目添加一个明显的区分标识就行了,根据这个标识判断项目和php版本,我是更改的入口文件,把index.php更改成index-prod.php,更改完是这样的
# 更改后的地址
rewrite "^/post/(\d{1,6}).html$" /index-prod.php?r=post/detail&id=$1 last;
# 没更改的地址
rewrite "^/article/(\d{1,6}).html$" /server/index.php?con=article&ac=detail&id=$1 last;
复制代码
完整的nginx配置是这样的:
server {
listen 80;
server_name www.test.com;
# 老项目的代码目录
root /var/www/test.com;
index index.php index.html index.htm index-prod.php;
location / {
# 更改后的地址
rewrite "^/post/(\d{1,6}).html$" /index-prod.php?r=post/detail&id=$1 last;
# 没更改的地址
rewrite "^/article/(\d{1,6}).html$" /server/index.php?con=article&ac=detail&id=$1 last;
}
# 匹配入口文件,判断是否要走新代码
location ~ index\-prod.php$ {
# 更改项目路径
root /var/www/new.test.com/frontend/web;
include snippets/fastcgi-php.conf;
# 更改新代码使用的PHP版本
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
}
# 默认走老代码
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_pass unix:/var/run/php/php5.3-fpm.sock;
}
}
复制代码
结语
通过上面的方法,我在不耽误正常业务开发的情况下,一点一点完成了核心业务的重构,虽然现在也没有重构完,但已经不影响新的开发和新的员工的融入。有些url改动几率很低功能也很稳定,所以就不动了,也不能为了重构而重构,毕竟我们还有好多工作。
nginx的功能有很多,上面只用了很少的一部分,感兴趣的朋友可以深入了解一下,一定会给你很多惊喜。上面有不对的地方,也欢迎大家指正。