PHP 8.5 升级指南 了解即将废弃的 11 个功能和完整迁移方案

AI摘要
本文为PHP 8.5升级指南,重点解析11项废弃功能及其迁移方案。核心建议是提前识别并替换废弃用法(如__sleep/__wakeup、反引号执行命令、非标准类型转换等),通过静态分析、测试环境预警、逐步重构确保平滑升级。强调保持代码兼容性,为PHP 9.0移除功能做准备,提升代码安全性与可维护性。

PHP 8.5 升级指南 了解即将废弃的 11 个功能和完整迁移方案

PHP 8.5 计划于 2025 年 11 月 20 日发布,带来了新功能、语法改进,当然还有废弃功能。废弃就是告诉你某些语言特性、函数或行为要在未来版本(通常是 PHP 9.0)中被移除或变得更严格。早点升级能避免代码出问题,保持兼容性,也能让你用上更现代、更安全的 PHP。

这篇文章我会讲:

  • PHP 8.5 中的主要废弃功能
  • 现有代码可能出现的问题
  • 替代/替换策略
  • 你可以遵循的迁移路线图

原文链接-PHP 8.5 升级指南 了解即将废弃的 11 个功能和完整迁移方案

PHP 8.5 中被废弃的功能

以下是 PHP 8.5 中最重要的一些废弃功能,主要来源于 PHP RFCs 和变更日志。

__sleep()__wakeup() 魔术方法

这些方法不能用了。改用 __serialize()__unserialize()

非标准的类型转换/标量转换名称

integerdoublebooleanbinary 这些转换名称不行了。要用标准形式:intfloatboolstring

使用反引号(`)作为 shell_exec() 的别名

反引号语法执行 shell 命令不能用了。换成 shell_exec()

在 array_key_exists() 中使用 null 作为数组偏移

null 作为键不行了。要传有效的键类型。

常量重复声明

同一个常量定义多次不行了。

某些 INI 指令的废弃

以下指令被废弃或移除:

  • report_memleaks
  • register_argc_argv(在 HTTP-SAPI 中)
  • disable_classes

标准库函数的 null 参数

readdir()rewinddir()closedir() 这些函数传 null 作为目录句柄不行了。

资源关闭/释放函数

手动关闭函数不能用了,现在资源都是对象,由析构函数自动处理。比如:

  • finfo_close()
  • xml_parser_free()
  • curl_close()
  • curl_share_close()
  • imagedestroy()

MHASH_* 常量

老的 MHASH_* 常量不能用了。改用现代哈希 API(hash()openssl)。

用户输出处理器返回非字符串

自定义输出缓冲处理器必须返回字符串。返回其他类型不行了。

从自定义输出缓冲处理器中发出输出

在自定义输出处理器里面直接输出内容不行了。

还有一些与边界情况下魔术方法相关的废弃,以及对 Directory 类的更改(例如,不允许 new Directory(),没有动态属性,不能克隆,不能序列化)。

你的代码可能出现的问题

废弃功能本身一般不会马上让代码挂掉——PHP 先会给你警告。但有些废弃功能会导致错误或不兼容,特别是:

  • 你开了严格的 error_reporting 或自定义错误处理器,把废弃当成错误处理
  • 你升级到 PHP 9.0 时,废弃功能直接被删掉了
  • 第三方库/插件在用废弃功能

容易踩坑的地方:

  • 用了 __sleep() / __wakeup() 的序列化逻辑,或者序列化的对象需要这些魔术方法
  • 老代码里用了非标准类型名称(比如 boolean 而不是 bool)做转换
  • 用反引号语法跑 shell 命令的代码——这个经常被忽略
  • 代码里有 array_key_exists(null, $array) 这种写法,或者给目录操作传 null 句柄
  • 自定义缓冲/输出处理器会输出或者期望非字符串数据
  • 用了 MHASH_* 常量的代码。老代码库或老包里经常有
  • Directory 对象上加动态属性,或者用 new Directory() 而不是 dir()

替换和替代策略

每个废弃功能怎么替换,看下面:

__sleep() / __wakeup()

改用 __serialize()__unserialize()。这俩更靠谱,向前兼容。如果要处理老的序列化数据,写个适配器支持两种格式。

非标准转换(integer、double、boolean、binary)

换成标准类型转换:intfloatboolstring。在代码库里搜索替换。PHPStan 或 Psalm 这些静态分析工具能帮你找出剩下的非标准转换。

反引号别名 shell_exec()

把反引号(`command`)换成 shell_exec('command')。这样更清楚、更安全,也能避免注入问题。

数组偏移中的 null(array_key_exists())

要传有效的键。如果键可能是 null,先处理一下:

  • 检查存在用 isset()
  • 检查对象属性用 property_exists()

常量重复声明

常量只定义一次。

  • 把重复的声明合并
  • 用命名空间来组织常量
  • 别条件性重复声明,除非真的需要

废弃的 INI 指令

从 php.ini 或 .user.ini 里删掉这些过时的指令:

  • report_memleaks
  • register_argc_argv(HTTP-SAPI)
  • disable_classes

确保你的应用不再依赖这些设置。

资源释放/关闭函数

让析构函数自动处理清理,别手动调用:

  • finfo_close()
  • xml_parser_free()
  • curl_close()
  • curl_share_close()
  • imagedestroy()

如果真的要手动释放,先检查对象是否有效,或者用更新的 API。

MHASH 常量

把老的 MHASH_* 常量换成现代哈希 API:

  • hash()
  • hash_hmac()
  • password_hash()
  • openssl_*() 函数

这样更安全,也向前兼容。

输出缓冲处理器

更新自定义输出处理器:

  • 必须返回字符串
  • 别在处理器里面直接输出。这样能保证各个 PHP 版本行为一致

Directory 类更改

别直接用 new Directory()。改用 dir()

  • 删掉动态属性赋值
  • 别克隆或序列化 Directory 对象
  • 检查代码库里的用法,该重构的重构

迁移路线图:如何安全升级

升级代码库(特别是中型/大型/老项目)到 PHP 8.5 不出问题,需要好好规划。实用路线图:

摸底

用静态分析工具(PHPStan、Psalm、PhpDepend)找废弃用法。

搜索这些模式:__sleep__wakeup、反引号、非标准转换、MHASH_* 等。

也要检查配置(php.ini)、自定义错误处理器、输出缓冲代码等。

开废弃警告

在开发/测试环境里,把 error_reporting 设成包含 E_DEPRECATEDE_WARNING

可以的话,把废弃当成要记录的事(或者让 CI 失败)来早点发现问题。

写兼容代码

序列化方面:如果要支持老的序列化数据,写个适配器同时支持 __sleep 风格和新方法。

老库用了废弃常量或行为的,考虑包装一下或者打个补丁。

一点点重构

从风险小的地方开始,比如小工具函数、内部代码、不重要的功能。

  • 换掉非标准类型转换
  • 删掉反引号用法
  • 换成新的哈希函数

好好测试

用单元测试和集成测试。确保行为(特别是序列化、输出缓冲、目录操作)还是对的。

测试还要验证新版本里不会有错误/废弃通知。

测试/预生产环境升 PHP 8.5

代码清理完了,在测试环境部署 PHP 8.5,开完整错误报告。盯着有没有新问题。

看日志,有问题就修。

为 PHP 9 做准备

8.5 里废弃的功能,9.0 里通常就直接删了,所以要确保代码向前兼容。

关注 PHP 9.0 的 RFCs。

更新依赖

很多第三方库可能也在用废弃功能。看看有没有支持 8.5 的库/框架新版本。

有些依赖如果被废弃了,可能要换掉。

需要注意的事项/陷阱

序列化格式兼容性:如果你用 __sleep/__wakeup 序列化过数据,存在会话、缓存、数据库里,你得处理反序列化这种格式。

魔术方法行为变化:一些边界行为(回退、返回 null)现在可能会警告;如果你的代码依赖这些,可能会收到警告或者行为变化。

动态属性:内置类(比如 Directory)或者删了 #[\AllowDynamicProperties] 的类,运行时加新属性现在可能会失败或警告。

INI 设置副作用:删掉废弃的 INI 指令可能会改变行为(比如 register_argc_argv),特别是 CLI vs HTTP 环境,或者跟某些第三方工具一起用的时候。

性能和错误噪音:如果用了很多废弃功能,开启废弃通知可能会刷屏日志。要想好怎么管理或者抑制(但别忽略)这些警告。

示例:重构一段代码

这里有一个具体的小例子。假设我们有:

<?php

class Legacy {
    public function __sleep(): array
    {
        // 清理或关闭逻辑
        return ['prop1', 'prop2'];
    }

    public function __wakeup()
    {
        // 重新初始化资源
    }

    public function run()
    {
        echo `ls -la`; // 使用反引号
        $val = (double) $this->someValue;
    }
}

重构后:

<?php

class Modern {
    public function __serialize(): array
    {
        // 清理或关闭逻辑
        return ['prop1' => $this->prop1, 'prop2' => $this->prop2];
    }

    public function __unserialize(array $data): void
    {
        $this->prop1 = $data['prop1'];
        $this->prop2 = $data['prop2'];
        // 重新初始化资源
    }

    public function run()
    {
        echo shell_exec('ls -la'); // 使用 shell_exec
        $val = (float) $this->someValue; // 使用标准转换
    }
}

总结

  • PHP 8.5 废弃的功能挺多,也很有针对性:魔术方法改了、类型转换标准化了、目录/资源处理更安全了、老常量废弃了等等
  • 很多不会马上让代码挂掉,但会警告,升级到 PHP 9.0 时可能就真挂了
  • 早点开始:在开发/测试环境开 E_DEPRECATED,看看哪里需要改
  • 用新的替换废弃功能(比如 __serialize()、标准类型、新库函数)
  • 更新依赖。用现代 PHP 功能让代码更干净、更安全、更好维护

升级到 PHP 8.5 不只是为了新功能——也是清理老代码的毛病、减少技术债、为以后做准备。有个靠谱的迁移计划,能减少麻烦,代码也会更精简、更强大。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 5
fatrbaby

可惜了 TrueAsync 没有合并

5小时前 评论
panus 3小时前
JaguarJack (楼主) 2小时前
syaoran 20分钟前
JaguarJack (楼主) 15分钟前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发 @ 家里蹲开发公司
文章
111
粉丝
80
喜欢
429
收藏
299
排名:18
访问:28.4 万
私信
所有博文
社区赞助商