-
match
现在是保留关键字。
-
mixed
现在是保留字,因此不能用于命名类、接口或特征,并且也不允许在命名空间中使用。
-
断言失败现在默认抛出。如果需要旧的行为,可以在 INI 设置中设置 assert.exception=0
。
-
与类同名的函数不再被解释为构造函数。应该改用 __construct() 方法。
-
已删除静态调用非静态方法的能力。因此,当检查具有类名的非静态方法时,is_callable() 将失败(必须使用对象实例进行检查)。
-
已删除 (real)
和 (unset)
转换。
-
已删除 track_errors ini 指令。这意味着 php_errormsg 不再可用。可以使用 error_get_last() 函数代替。
-
已删除定义不区分大小写的常量的能力。define() 的第三个参数不再可以是 true
。
-
已删除使用 __autoload() 函数指定自动加载程序的能力。应改用 spl_autoload_register()。
-
errcontext
参数将不再传递给使用 set_error_handler() 设置的自定义错误处理程序。
-
create_function() 已被删除。可以使用匿名函数代替。
-
each() 已被删除。应改用 foreach 或 ArrayIterator。
-
已删除使用 Closure::fromCallable() 或 ReflectionMethod::getClosure() 从方法创建的闭包中解除绑定 this 的能力。
-
还删除了从包含 this 用法的正确闭包中解除绑定 this 的能力。
-
已删除使用 array_key_exists() 与对象的能力。可以使用 isset() 或 property_exists() 代替。
-
已使 array_key_exists() 关于 key
参数类型的行为与 isset() 和普通数组访问保持一致。所有键类型现在都使用通常的强制转换,并且数组/对象键会抛出 TypeError。
-
任何以数字 n 作为其第一个数字键的数组都将对下一个隐式键使用 n+1,即使 n 为负数。
-
默认的 error_reporting 级别现在是 E_ALL
。以前它排除了 E_NOTICE
和 E_DEPRECATED
。
-
display_startup_errors 现在默认启用。
-
在没有父类的类中使用 parent 现在将导致致命编译时错误。
-
@
运算符将不再抑制致命错误 (E_ERROR
、E_CORE_ERROR
、E_COMPILE_ERROR
、E_USER_ERROR
、E_RECOVERABLE_ERROR
、E_PARSE
)。应调整预期 @
使用时 error_reporting
为 0
的错误处理程序以改用掩码检查
<?php
// 替换
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (error_reporting() == 0) {
return false;
}
// ...
}
// 使用
function my_error_handler($err_no, $err_msg, $filename, $linenum) {
if (!(error_reporting() & $err_no)) {
return false;
}
// ...
}
?>
此外,应注意在生产环境中不显示错误消息,这可能导致信息泄漏。请确保将 display_errors=Off
与错误日志一起使用。
-
#[
不再被解释为注释的开始,因为此语法现在用于属性。
-
由于不兼容的方法签名(LSP 违规)导致的继承错误现在将始终生成致命错误。以前在某些情况下会生成警告。
-
连接运算符的优先级相对于位移和加法以及减法发生了变化。
<?php
echo "Sum: " . $a + $b;
// 之前被解释为:
echo ("Sum: " . $a) + $b;
// 现在被解释为:
echo "Sum:" . ($a + $b);
?>
-
具有默认值且在运行时解析为**null
**的参数将不再隐式地将参数类型标记为可为空。必须改用显式可为空类型或显式**null
**默认值。
<?php
// 替换
function test(int $arg = CONST_RESOLVING_TO_NULL) {}
// 为
function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
// 或
function test(int $arg = null) {}
?>
-
一些警告已转换为Error异常。
- 尝试写入非对象的属性。之前,这会为 null、false 和空字符串隐式创建 stdClass 对象。
- 尝试向数组追加元素,而该数组已使用 PHP_INT_MAX 键。
- 尝试使用无效类型(数组或对象)作为数组键或字符串偏移量。
- 尝试写入标量值的数组索引。
- 尝试解包非数组/可遍历对象。
- 尝试访问未定义的非限定常量。之前,非限定常量访问会导致警告,并被解释为字符串。
- 向非可变内置函数传递错误数量的参数将抛出ArgumentCountError。
- 向count()传递无效的可计数类型将抛出TypeError。
一些通知已转换为警告。
- 尝试读取未定义的变量。
- 尝试读取未定义的属性。
- 尝试读取未定义的数组键。
- 尝试读取非对象的属性。
- 尝试访问非数组的数组索引。
- 尝试将数组转换为字符串。
- 尝试使用资源作为数组键。
- 尝试使用 null、布尔值或浮点数作为字符串偏移量。
- 尝试读取超出范围的字符串偏移量。
- 尝试将空字符串分配给字符串偏移量。
-
尝试将多个字节分配给字符串偏移量现在将发出警告。
-
源文件中的意外字符(例如字符串之外的 NUL 字节)现在将导致ParseError异常,而不是编译警告。
-
未捕获的异常现在将经过“干净关闭”,这意味着析构函数将在未捕获的异常之后被调用。
-
编译时致命错误“Only variables can be passed by reference”已延迟到运行时,并转换为“Argument cannot be passed by reference”Error异常。
-
一些“Only variables should be passed by reference”通知已转换为“Argument cannot be passed by reference”异常。
-
匿名类的生成名称已更改。它现在将包含第一个父类或接口的名称。
<?php
new class extends ParentClass {};
// -> ParentClass@anonymous
new class implements FirstInterface, SecondInterface {};
// -> FirstInterface@anonymous
new class {};
// -> class@anonymous
?>
上面显示的名称后面仍然跟着一个 NUL 字节和一个唯一的后缀。
-
现在要求特性别名适配中的非绝对特性方法引用是明确的。
<?php
class X {
use T1, T2 {
func as otherFunc;
}
function func() {}
}
?>
如果 T1::func()
和 T2::func()
都存在,则此代码之前会被静默接受,并且 func 被假定为引用 T1::func
。现在它将改为生成致命错误,并且需要显式写入 T1::func
或 T2::func
。
-
现在将根据实现类的方 法检查特性中定义的抽象方法的签名。
<?php
trait MyTrait {
abstract private function neededByTrait(): string;
}
class MyClass {
use MyTrait;
// 错误,因为返回类型不匹配。
private function neededByTrait(): int { return 42; }
}
?>
-
现在禁用函数的处理方式与不存在的函数完全相同。调用禁用函数将将其报告为未知,并且现在可以重新定义禁用函数。
-
data://
流包装器不再可写,这与文档记录的行为相匹配。
-
算术和位运算符 +
、-
、*
、/
、**
、%
、<<
、>>
、&
、|
、^
、~
、++
、--
现在将在其中一个操作数为array、resource或非重载object时始终抛出TypeError。唯一的例外是数组 +
数组合并操作,它仍然受支持。
-
浮点数到字符串的转换现在将始终以与区域设置无关的方式运行。
<?php
setlocale(LC_ALL, "de_DE");
$f = 3.14;
echo $f, "\n";
// 之前:3,14
// 现在:3.14
?>
有关自定义数字格式的方法,请参阅printf()、number_format()和NumberFormatter()。
-
已删除对用于偏移量访问的已弃用花括号的支持。
<?php
// 而不是:
$array{0};
$array{"key"};
// 写:
$array[0];
$array["key"];
?>
-
现在,除非该方法是构造函数,否则在私有方法上应用 final 修饰符将产生警告。
-
如果对象的构造函数exit(),则将不再调用对象的析构函数。这与构造函数抛出异常时的行为相匹配。
-
命名空间名称不再包含空格:虽然 Foo\Bar
将被识别为命名空间名称,但 Foo \ Bar
不会。相反,现在允许使用保留关键字作为命名空间段,这也可能会更改代码的解释:new\x
现在与 constant('new\x')
相同,而不是 new \x()
。
-
嵌套的三元运算符现在需要显式括号。
-
debug_backtrace()和Exception::getTrace()将不再提供对参数的引用。无法通过回溯更改函数参数。
-
数字字符串处理已更改为更直观且更不容易出错。现在,为了与处理前导空格的方式保持一致,数字字符串中允许使用尾随空格。这主要影响
“前导数字字符串”的概念已基本取消;保留此概念的案例是为了简化迁移。发出E_NOTICE
“A non well-formed numeric value encountered”的字符串现在将发出E_WARNING
“A non-numeric value encountered”,并且所有发出E_WARNING
“A non-numeric value encountered”的字符串现在将抛出TypeError。这主要影响
将此E_WARNING
更改为TypeError也会影响非法的字符串偏移量导致的E_WARNING
“Illegal string offset 'string'”。从字符串到 int/float 的显式转换行为没有改变。
-
如果魔术方法声明了参数和返回值类型,现在将对其进行检查。签名应与以下列表匹配
__call(string $name, array $arguments): mixed
__callStatic(string $name, array $arguments): mixed
__clone(): void
__debugInfo(): ?array
__get(string $name): mixed
__invoke(mixed $arguments): mixed
__isset(string $name): bool
__serialize(): array
__set(string $name, mixed $value): void
__set_state(array $properties): object
__sleep(): array
__unserialize(array $data): void
__unset(string $name): void
__wakeup(): void
-
call_user_func_array() 数组键现在将被解释为参数名称,而不是被静默忽略。
-
在命名空间内声明名为assert()
的函数不再允许,并会发出E_COMPILE_ERROR
错误。 assert() 函数受引擎的特殊处理,在定义具有相同名称的命名空间函数时,可能会导致不一致的行为。