-
match
现在是一个保留字。
-
断言(Assertion)失败现在默认抛出异常。如果想要改回之前的行为,可以在 INI 设置中设置
assert.exception=0
。
-
mixed
现在是保留字,所以不能用于类,接口或者
trait,也禁止在命名空间中使用。
-
与类名相同的方法名将不再被当做构造方法。应该使用 __construct()
来取代它。
-
不再允许通过静态调用的方式去调用非静态方法。因此 is_callable() 在检查一个类名与非静态方法时将返回失败(应当检查一个类的实例)。
-
(real)
和 (unset)
转换已被移除。
-
移除 track_errors 执行。这意味着不能再用 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() 和正常数组访问一致。所有的
key 类型现在使用通用的强制转换,数组/对象 key 会抛出 TypeError。
-
任意一个数组,将数字 n 作为第一个数字 key,下一个隐式键将会是 n+1。即使
n 为负数也是如此。
-
error_reporting 默认级别现在是 E_ALL
。之前排除 E_NOTICE
和 E_DEPRECATED
。
-
现在默认启用 display_startup_errors。
-
在没有父级的类中使用 parent 将会导致 fatal compile-time 错误。
-
@
操作将不再屏蔽 fatal
错误(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。必须改用指定可为 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 作为 key 的数组。
-
尝试使用无效类型(array 或 object)作为数组的 key 或者字符串的 offset。
- 尝试向标量值写入数组索引。
- 尝试解包非数组或 Traversable。
-
尝试访问未定义的常量,之前,访问未定义的常量将会导致警告并解释为字符串。
-
传递错误的参数数量到非可变参数内置函数将引发 ArgumentCountError。
-
传递无效的可数的类型到 count() 将抛出 TypeError。
一些通知已转换为警告:
- 尝试读取未定义的变量。
- 尝试读取未定义的属性。
- 尝试读取未定义的数组 key。
- 尝试读取非对象的属性。
- 尝试读取非数组的数组索引。
- 尝试转换数组为字符串。
- 尝试使用资源作为数组 key。
- 尝试使用 null、bool、float 作为字符串 offset。
- 尝试读取越界的字符串 offset。
- 尝试将空字符串分配给字符串 offset。
-
尝试将多字节字符串分配给字符串 offset 现在将发出警告。
-
源文件中的异常字符(比如字符串边界外的 NUL 字节)现在将导致 ParseError 异常而不是编译警告。
-
未捕获异常现在会经过“clean shutdown”,这意味着未捕获的异常之后调用析构方法。
-
编译时 fatal error“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 字节和唯一的后缀。
-
trait 别名适配中的非绝对 trait 方法引用现在必须明确:
<?php
class X {
use T1, T2 {
func as otherFunc;
}
function func() {}
}
?>
如果同时存在 T1::func()
和 T2::func()
,以前此代码会默默接受,并且 func 指向
T1::func
。现在则会生成 fatal error,必须明确编写 T1::func
or T2::func
。
-
trait 中定义的 abstract 方法签名现在会检查类中实现的方法:
<?php
trait MyTrait {
abstract private function neededByTrait(): string;
}
class MyClass {
use MyTrait;
// 错误,因为返回类型不匹配。
private function neededByTrait(): int { return 42; }
}
?>
-
现在将禁用的函数视为不存在的函数,调用禁用函数将报告未知,并且现在可以重新定义已禁用的函数。
-
data://
流封装协议不在可写,这与文档中的行为相匹配。
-
算术和位操作符 +
、-
、*
、/
、**
、%
、<<
、>>
、&
、|
、^
、~
、++
、--
的其中一个操作符是 array、resource 或非重载 object 时,现在将始终抛出
TypeError。唯一的例外是仍然支持 array +
array 的合并操作。
-
浮点数到字符串的强制转换现在始终不会受到独立 locale 的影响。
<?php
setlocale(LC_ALL, "de_DE");
$f = 3.14;
echo $f, "\n";
// Previously: 3,14
// Now: 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()
函数受引擎的特殊处理,当定义具有相同名称的命名空间函数时,可能会导致不一致的行为。