从PHP 7.3升级到8.3必须修改三类代码:废弃函数调用(如each、create_function、mysql_*、assert字符串参数)、字符串/数组误用($str{0}→$str[0]、null/undefined键访问、字符串展开)、动态属性访问(未声明属性赋值默认报ValueError);不改将直接触发Fatal error或TypeError。

直接说结论:从 PHP 7.3 升级到 8.3,你大概率要改三类代码——废弃函数调用、字符串/数组误用、以及所有未声明类型的动态属性访问。不改就跑不起来,不是警告,是 Fatal error 或 ValueError。
哪些函数必须立刻替换
PHP 8.3 已彻底移除一批在 7.3 里还能用但早已标为 deprecated 的函数,调用即崩:
-
each():全局搜each(,全替成foreach;别留任何侥幸,它在 8.0 就没了 -
create_function():搜create_function(,换成fn()或function();注意闭包变量捕获逻辑是否一致 -
mysql_*系列(mysql_connect、mysql_query等):必须换成mysqli或PDO;光替换函数名没用,连接对象、错误处理方式全得重写 -
assert()字符串参数:如assert('is_int($x)')会直接报ParseError,改成assert(is_int($x))
字符串和数组下标访问容易静默变错
PHP 8.3 对类型更“较真”,很多以前能蒙混过关的写法现在直接报错:
- 用花括号取字符串单字符:
$str{0}→ 必须改成$str[0]或str_split($str)[0] - 对
null或int做数组式访问:$x = null; echo $x['key'];→ 报TypeError;加isset($x['key'])或先判断类型 - 访问未定义数组键:
$arr['missing']→ 不再是Notice,而是ValueError(除非启用了#[AllowDynamicProperties]) - 把字符串当数组展开:
[$str, ...$other]→ 8.3 会报TypeError: Cannot unpack string,先str_split()再展开
动态属性和未声明属性现在默认禁止
PHP 8.3 默认禁用动态属性($obj->undefined_prop = 'xxx'),老项目里大量使用的魔术方法或 stdClass 赋值会直接炸:
立即学习“PHP免费学习笔记(深入)”;
- 检查所有
stdClass实例赋值,比如$user = new \stdClass(); $user->email = 'x';→ 若没加#[AllowDynamicProperties],运行时抛ValueError - 自定义类中没声明却在
__set()里赋值的属性,同样触发错误;要么提前声明public $email;,要么改用属性数组模拟($this->data['email'] = 'x') - 框架如 Yii 1.x 或某些老旧 SDK 可能依赖此行为,必须实测;
class_exists('yii\base\Object')返回true就说明还残留兼容层,得清缓存或升级
构造器参数和类型声明要对齐
PHP 8.3 强化了继承与实现契约,父类方法签名一动,子类不跟着改就失效:
- 子类覆写父类方法时,参数类型不能比父类更宽(逆变规则);例如父类是
function save(string $id),子类写成function save(mixed $id)会报TypeError - 构造器里用属性提升(
public function __construct(public string $name))没问题,但若父类构造器有类型提示,子类__construct()必须保持兼容 - 接口方法返回类型声明必须严格匹配;以前宽松的
function get(): array,若实现类返回string[],8.3 会报错,得统一成array|string[]或用联合类型
最常被忽略的一点:php -v 显示的是 CLI 版本,Web 服务器(如 Nginx + php-fpm)可能还在跑旧版。务必确认两者都是 8.3.x,否则测试通过上线就挂。



















