-
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 的能力。
-
The ability to unbind this from proper closures that contain uses of
this has also been removed.
-
移除对对象使用 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。
-
尝试访问未定义的常量,之前,访问未定义的常量将会导致警告并解释为字符串。
一些通知已转换为警告:
- 尝试读取未定义的变量。
- 尝试读取未定义的属性。
- 尝试读取未定义的数组 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”异常。
-
The generated name for anonymous classes has changed. It will now include the name of the first
parent or interface:
<?php
new class extends ParentClass {};
// -> ParentClass@anonymous
new class implements FirstInterface, SecondInterface {};
// -> FirstInterface@anonymous
new class {};
// -> class@anonymous
?>
The name shown above is still followed by a NUL byte and a unique suffix.
-
Non-absolute trait method references in trait alias adaptations are now required to be
unambiguous:
<?php
class X {
use T1, T2 {
func as otherFunc;
}
function func() {}
}
?>
If both T1::func()
and T2::func()
exist, this code was previously
silently accepted, and func was assumed to refer to T1::func
. Now it will generate a
fatal error instead, and either T1::func
or T2::func
needs to be
written explicitly.
-
The signature of abstract methods defined in traits is now checked against the implementing class
method:
<?php
trait MyTrait {
abstract private function neededByTrait(): string;
}
class MyClass {
use MyTrait;
// Error, because of return type mismatch.
private function neededByTrait(): int { return 42; }
}
?>
-
Disabled functions are now treated exactly like non-existent functions. Calling a disabled
function will report it as unknown, and redefining a disabled function is now possible.
-
data://
stream wrappers are no longer writable, which matches the documented
behavior.
-
The arithmetic and bitwise operators +
, -
,
*
, /
, **
, %
,
<<
, >>
, &
,
|
, ^
, ~
, ++
,
--
will now consistently throw a TypeError when one of
the operands is an array, 资源(resource) or non-overloaded object. The only exception to this is
the array +
array merge operation, which remains supported.
-
Float to string casting will now always behave locale-independently.
<?php
setlocale(LC_ALL, "de_DE");
$f = 3.14;
echo $f, "\n";
// Previously: 3,14
// Now: 3.14
?>
See printf(), number_format() and
NumberFormatter() for ways to customize number formatting.
-
Support for deprecated curly braces for offset access has been removed.
<?php
// Instead of:
$array{0};
$array{"key"};
// Write:
$array[0];
$array["key"];
?>
-
Applying the final modifier on a private method will now produce a warning unless that method is
the constructor.
-
If an object constructor exit()s, the object destructor will no longer be
called. This matches the behavior when the constructor throws.
-
Namespaced names can no longer contain whitespace: While Foo\Bar
will be recognized
as a namespaced name, Foo \ Bar
will not. Conversely, reserved keywords are now
permitted as namespace segments, which may also change the interpretation of code:
new\x
is now the same as constant('new\x')
, not
new \x()
.
-
Nested ternaries now require explicit parentheses.
-
debug_backtrace() and Exception::getTrace() will no
longer provide references to arguments. It will not be possible to change function arguments
through the backtrace.
-
Numeric string handling has been altered to be more intuitive and less error-prone. Trailing
whitespace is now allowed in numeric strings for consistency with how leading whitespace is
treated. This mostly affects:
- The is_numeric() function
- String-to-string comparisons
- Type declarations
- Increment and decrement operations
The concept of a "leading-numeric string" has been mostly dropped; the cases where this remains
exist in order to ease migration. Strings which emitted an E_NOTICE
"A non
well-formed numeric value encountered" will now emit an E_WARNING
"A
non-numeric value encountered" and all strings which emitted an E_WARNING
"A
non-numeric value encountered" will now throw a
TypeError. This mostly affects:
- Arithmetic operations
- Bitwise operations
This E_WARNING
to TypeError change also affects the
E_WARNING
"Illegal string offset 'string'" for illegal string offsets. The
behavior of explicit casts to int/float from strings has not been changed.
-
Magic Methods will now have their arguments and return types checked if they have them declared.
The signatures should match the following list:
__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() array keys will now be interpreted as parameter names,
instead of being silently ignored.
-
Declaring a function called assert()
inside a namespace is
no longer allowed, and issues E_COMPILE_ERROR
.
The assert() function is subject to special handling by the engine,
which may lead to inconsistent behavior when defining a namespaced function with the same name.