cbasil
V2EX  ›  PHP

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

  •  
  •   cbasil · 8h 35m ago · 1945 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 一定会困难重重,但是一旦开始执行,一个个问题解决也发现其实也很容易就处理了。
    31 replies  •  2026-10-29 19:19:16 +08:00
    SoulFlame
        1
    SoulFlame  
       8h 32m ago
    修复漏洞的紧急时期做项目版本升级太匆忙了,容易忙中出错。
    我低版本项目全部都是保持版本的,给 PHP 打补丁就好了,社区有很多大佬基于官方 PHP7.4 补丁包给低版本打的补丁代码
    ModiKa2022
        3
    ModiKa2022  
       8h 24m ago
    @SoulFlame 公司还是选择升级到 8.4 的方案了,一次性清理遗留问题, 线上报错, 立即解决, 肯定有一个过渡期, 现在修改代码的成本太低了
    adoal
        4
    adoal  
       8h 24m ago
    个人的项目经验:大量数据导出之类的耗时操作,最好设计成后台异步执行的方式,导出过程的进度和结果通过消息传递跟 UI 交互,导出结果放在服务器的下载区一段时间或者扔到对象存储。这样提交了任务就可以关掉 UI 不管了,导出结束之后再下载文件。
    cbasil
        5
    cbasil  
    OP
       8h 22m ago
    @SoulFlame 最主要是这个项目以后还是要正常运营,也是一个盈利项目,后续还可能会有功能新增,所以升级到最新版本也有利于后续开发维护。
    FrankAdler
        6
    FrankAdler  
       8h 20m 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  
       8h 16m ago
    @ModiKa2022 #3
    @cbasil #5 项目升级 PHP 大版本有很多不可控的因素的,升级完成到百分百覆盖测试,其实需要很多功夫,如果测试不到位,有一定规模的项目,如果数据库产生了脏数据,那后果将是灾难性的。
    而且如果此漏洞易利用的话,在你升级这段时间,你的项目是暴露在非常大的风险之中(幸运的是此次漏洞虽然危害大,但是并不容易利用)。

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

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