cbasil
V2EX  ›  PHP

php5.6 升级到 php8.3.36 踩的一些坑

  •  
  •   cbasil · 6h 19m ago · 1563 views
    最近 php 爆出了 9.3 分的严重漏洞,我负责的一个项目 php 版本是 5.6 ,之前也一直想把它升级到 7 以上的版本,但是觉得改动太大就没有动它。这次不得不升级了。

    第一步:本地搭建 php8.3.36 环境,然后用 claude code 做兼容性检查修复并导出 excel 文件,共检查出 284 出不兼容,常见的问题是:数据库返回类型、des 加密、已移除函数、类型错误问题。

    第二步:搭建和生产环境一样的测试环境,测试覆盖常用业务。

    第三部:在生产环境通过 remi 安装 php8.3.36 。另外新建目录将修改后的代码上传到该目录。新建 apache 配置,将 prod-test 域名指向该配置。测试无误后把项目入口文件内容改成系统升级中提示,然后上传最新代码到项目文件。上传完成后把 apache 配置 php mod 改成 8.3 。然后重启 apache 完成升级。

    升级后遇到的几个问题
    第一:php5.6 不受 apache 配置 Timeout 的影响,而 php8.3 则会。上线后后台做大数据导出统计时报:The server is temporarily unable to service your request due to maintenance downtime or capacity problems. 后面将 apache Timeout 改成 120s 解决。

    第二:升级后系统定时任务执行失败,通过执行:grep -E 'CROND.*CMDOUT|CROND.*CMD' /var/log/cron | tail -50 查出 cron 任务执行时 php 指向的还是 php5.6,后面将任务里的 php 改成 php8.3 解决。

    第三:array_multisort 数组排序在 php8.3 中报错 Array sizes are inconsistent ,原因时多个数组元素数量不一致导致。

    第四:json 解析时会报:json_decode(): Argument #1 ($json) must be of type string, 处理方案时解析前判断参数是否为字符串和是否为空。

    总结:从周漏洞爆发到周日升级,总共用时 3 天解决。现在有 ai 辅助,修改代码比之前简单多了,但是 ai 也不是万能的,像类型定义错误、json 解析和数组问题 ai 都没有检查出来。以前觉得从 5.6 升级到 8.3 一定会困难重重,但是一旦开始执行,一个个问题解决也发现其实也很容易就处理了。
    28 replies  •  2026-10-29 16:37:47 +08:00
    SoulFlame
        1
    SoulFlame  
       6h 16m ago
    修复漏洞的紧急时期做项目版本升级太匆忙了,容易忙中出错。
    我低版本项目全部都是保持版本的,给 PHP 打补丁就好了,社区有很多大佬基于官方 PHP7.4 补丁包给低版本打的补丁代码
    ModiKa2022
        3
    ModiKa2022  
       6h 7m ago
    @SoulFlame 公司还是选择升级到 8.4 的方案了,一次性清理遗留问题, 线上报错, 立即解决, 肯定有一个过渡期, 现在修改代码的成本太低了
    adoal
        4
    adoal  
       6h 7m ago
    个人的项目经验:大量数据导出之类的耗时操作,最好设计成后台异步执行的方式,导出过程的进度和结果通过消息传递跟 UI 交互,导出结果放在服务器的下载区一段时间或者扔到对象存储。这样提交了任务就可以关掉 UI 不管了,导出结束之后再下载文件。
    cbasil
        5
    cbasil  
    OP
       6h 6m ago
    @SoulFlame 最主要是这个项目以后还是要正常运营,也是一个盈利项目,后续还可能会有功能新增,所以升级到最新版本也有利于后续开发维护。
    FrankAdler
        6
    FrankAdler  
       6h 3m ago
    隐性的,不会报错但是行为发生的改变,不敢升级啊,比如这种:
    比较 之前 之后
    0 == "0" true true
    0 == "0.0" true true
    0 == "foo" true false
    0 == "" true false
    42 == " 42" true true
    42 == "42foo" true false
    SoulFlame
        7
    SoulFlame  
       6h 0m ago
    @ModiKa2022 #3
    @cbasil #5 项目升级 PHP 大版本有很多不可控的因素的,升级完成到百分百覆盖测试,其实需要很多功夫,如果测试不到位,有一定规模的项目,如果数据库产生了脏数据,那后果将是灾难性的。
    而且如果此漏洞易利用的话,在你升级这段时间,你的项目是暴露在非常大的风险之中(幸运的是此次漏洞虽然危害大,但是并不容易利用)。

    所以我个人还是更赞成第一时间紧急做对应 PHP 版本的补丁修复(这可能只需要花费你 1-2 个小时)。后续再慢慢做 PHP 大版本升级。
    yuewolf
        8
    yuewolf  
       6h 0m ago
    @FrankAdler 可以交给 AI 的
    cbasil
        9
    cbasil  
    OP
       6h 0m ago
    @ModiKa2022 是的,升级版本还是目前比较稳妥的办法,毕竟 php 代码改动是最快的,有问题修复完直接 ftP 上传就完事。
    FrankAdler
        10
    FrankAdler  
       5h 58m ago
    @yuewolf 那得让 AI 把所有的代码都扫一遍才行了,不敢想得用多少 token
    Felldeadbird
        11
    Felldeadbird  
       5h 55m ago
    我丢给 AI 修复了快一周了,还没全面迁移完毕。不可控的太多了。
    cbasil
        12
    cbasil  
    OP
       5h 54m ago
    @FrankAdler 交给 ai 处理,另外类似这种写法 42 == "42foo"其实应该是不允许的,之前 php 给我们太宽松了。自从开始写 golang 后,我对这种比较都会先转换成同类型再对比。
    FrankAdler
        13
    FrankAdler  
       5h 49m ago
    @cbasil php 是弱类型的,人工不会写 42 == "42foo",但是可能有变量的值是这样,比如是来自外部输入,这才是问题根源,而且应该挺难发现的
    lmmlwen
        14
    lmmlwen  
       5h 42m ago
    php5.6 敢升级那说明你们项目债务少且业务简单
    icanfork
        15
    icanfork  
       5h 39m ago
    从 PHP7.1 升到了 PHP8.4 ,目前一切安好中。
    z1154505909
        16
    z1154505909  
       5h 30m ago
    把 tp3.1 的项目用 tp8 重写了。mmp.那项目当初一开始我就想用 tp8 写,动手的时候想到 tp3 那么老,依赖的 php 版本也老出点问题,都不好弄,不行就要用那个老的改,摁回去让我用 tp3 的老项目改,真出问题了,还是得我来擦屁股,花了加倍的成本。
    cbasil
        17
    cbasil  
    OP
       5h 23m ago
    @lmmlwen 这个项目从开发到现在也快 10 年了,有自营商城(包含在线购药)、车类服务业务(洗车、加油、维修等)、美团外卖、话费视频充值类和家政服务等,大大小小业务也有上百项。还有很多跟客户、供应商对接的 api 接口。
    zhhqiang
        18
    zhhqiang  
       3h 32m ago
    我这基本上都是 php 项目,还好 bt 用的多一点,补丁上了,5.6 的切换到 7.2 也还行。
    furlxy
        19
    furlxy  
       3h 28m ago
    都 AI 了,为啥不直接 8.5.12
    我这有个 phpmywind 的老 cms ,让 codex 一下午都改完了
    Plutooo
        20
    Plutooo  
       3h 23m ago
    有这精力升级其实不如换个语言重写了
    Rache1
        21
    Rache1  
       2h 54m ago
    有个问题,你们这项目全是你们自己的代码手搓的吗?

    如果之前没有测试覆盖, 用到了第三方包,那你那么多第三方包也要跟着升级,很多都可能要涉及到大版本升级了,你们怎么覆盖,还是等爆炸
    cbasil
        22
    cbasil  
    OP
       2h 32m ago
    @Rache1 有框架的,改的地方一般只要改业务代码就行,以前老项目用 yii 或者 laravel 框架。新的项目现在都用 go 了。
    Rache1
        23
    Rache1  
       2h 30m ago
    @cbasil #22 但是你也得更新框架和那些第三方的版本吧,而且这么大的版本跨度的话,大多第三方包应该也有不少的兼容中断的更新了,我觉得这才是最麻烦的地方 ,单框架本身还好,担心的是业务中的引用第三方的包这些,不过 AI 似乎也能照顾到,但是测试覆盖率不够的话,还是感觉有点悬着的
    V2Try
        24
    V2Try  
       2h 27m ago via iPhone
    我们的也迁移了,最大感觉是 php8 的错误处理太严格了,以前只是 warning 的直接就是 fatal error ,不过也好,容易发现问题,用 ai 修也快。
    cbasil
        25
    cbasil  
    OP
       2h 25m ago
    @Plutooo 那估计是不行的,这个项目有上百项业务,牵扯的供应商更多,换语言那就不是几天就能搞定的了,单纯的接口联调测试都会把人搞疯。
    pandamen
        26
    pandamen  
       2h 20m ago
    我直接 7.4 升级到 8.4 ,到目前没有发现问题
    cbasil
        27
    cbasil  
    OP
       59 mins ago
    @Rache1 第三方包比较少,大部分都是手搓的,包括微信支付、阿里云 oss 。
    nolynfeng
        28
    nolynfeng  
       39 mins ago
    直接让 ai 升级的,php8.0.29 干到 php8.5.12,线上已经切完了,暂时没发现问题,发现了就跑路
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4813 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 66ms · UTC 09:16 · PVG 17:16 · LAX 02:16 · JFK 05:16
    ♥ Do have faith in what you're doing.