数字与非数字形式的字符串之间的非严格比较现在将首先将数字转为字符串,然后比较这两个字符串。
数字与数字形式的字符串之间的比较仍然像之前那样进行。
请注意,这意味着 0 == "not-a-number"
现在将被认为是 false 。
Comparison | Before | After |
---|---|---|
0 == "0" |
true |
true |
0 == "0.0" |
true |
true |
0 == "foo" |
true |
false |
0 == "" |
true |
false |
42 == " 42" |
true |
true |
42 == "42foo" |
true |
false |
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 异常:
一些通知已转换为警告:
尝试将多字节字符串分配给字符串 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 修饰符现在将产生警告,除非该方法是构造方法。
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 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:
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.
Several 资源(resource)s have been migrated to objects.
Return value checks using is_resource() should be replaced with checks for false
.
curl_init() will now return a CurlHandle object rather than a 资源(resource). The curl_close() function no longer has an effect, instead the CurlHandle instance is automatically destroyed if it is no longer referenced.
curl_multi_init() will now return a CurlMultiHandle object rather than a 资源(resource). The curl_multi_close() function no longer has an effect, instead the CurlMultiHandle instance is automatically destroyed if it is no longer referenced.
curl_share_init() will now return a CurlShareHandle object rather than a 资源(resource). The curl_share_close() function no longer has an effect, instead the CurlShareHandle instance is automatically destroyed if it is no longer referenced.
enchant_broker_init() will now return an EnchantBroker object rather than a 资源(resource).
enchant_broker_request_dict() and enchant_broker_request_pwl_dict() will now return an EnchantDictionary object rather than a 资源(resource).
The GD extension now uses GdImage objects as the underlying data structure for images, rather than 资源(resource)s. The imagedestroy() function no longer has an effect; instead the GdImage instance is automatically destroyed if it is no longer referenced.
openssl_x509_read() and openssl_csr_sign() will now return an OpenSSLCertificate object rather than a 资源(resource). The openssl_x509_free() function is deprecated and no longer has an effect, instead the OpenSSLCertificate instance is automatically destroyed if it is no longer referenced.
openssl_csr_new() will now return an OpenSSLCertificateSigningRequest object rather than a 资源(resource).
openssl_pkey_new() will now return an OpenSSLAsymmetricKey object rather than a 资源(resource). The openssl_pkey_free() function is deprecated and no longer has an effect, instead the OpenSSLAsymmetricKey instance is automatically destroyed if it is no longer referenced.
shmop_open() 现在将返回 Shmop 对象而不是 资源(resource)。shmop_close() 函数将不再有效,已弃用;如果不在引用 Shmop 实例,其将会自动销毁。
socket_create(), socket_create_listen(), socket_accept(), socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind(), and socket_wsaprotocol_info_import() will now return a Socket object rather than a 资源(resource). socket_addrinfo_lookup() will now return an array of AddressInfo objects rather than 资源(resource)s.
msg_get_queue() will now return an SysvMessageQueue object rather than a 资源(resource).
sem_get() will now return an SysvSemaphore object rather than a 资源(resource).
shm_attach() will now return an SysvSharedMemory object rather than a 资源(resource).
xml_parser_create() and xml_parser_create_ns() will now return an XMLParser object rather than a 资源(resource). The xml_parser_free() function no longer has an effect, instead the XmlParser instance is automatically destroyed if it is no longer referenced.
The XMLWriter functions now accept and return, respectively, XMLWriter objects instead of 资源(resource)s.
inflate_init() will now return an InflateContext object rather than a 资源(resource).
deflate_init() will now return a DeflateContext object rather than a 资源(resource).
The ability to import case-insensitive constants from type libraries has been removed. The second argument to com_load_typelib() may no longer be false; com.autoregister_casesensitive may no longer be disabled; case-insensitive markers in com.typelib_file are ignored.
CURLOPT_POSTFIELDS
no longer accepts objects as arrays. To
interpret an object as an array, perform an explicit (array)
cast. The
same applies to other options accepting arrays as well.
mktime() and gmmktime() now require at least one argument. time() can be used to get the current timestamp.
Unimplemented classes from the DOM extension that had no behavior and contained test data have been removed. These classes have also been removed in the latest version of the DOM standard:
DOM 扩展中没有实现行为的方法已被删除:
enchant_broker_list_dicts(), enchant_broker_describe() and
enchant_dict_suggest() will now return an empty array instead of null
.
read_exif_data() has been removed; exif_read_data() should be used instead.
The FILTER_FLAG_SCHEME_REQUIRED
and
FILTER_FLAG_HOST_REQUIRED
flags for the
FILTER_VALIDATE_URL
filter have been removed. The scheme
and host
are (and have been) always required.
The INPUT_REQUEST
and INPUT_SESSION
source for
filter_input() etc. have been removed. These were never implemented and their
use always generated a warning.
移除弃用函数 image2wbmp()。
移除弃用函数 png2wbmp() 和 jpeg2wbmp()。
The default mode
parameter of imagecropauto() no longer
accepts -1
. IMG_CROP_DEFAULT
should be used instead.
On Windows, php_gd2.dll has been renamed to php_gd.dll.
gmp_random() has been removed. One of gmp_random_range() or gmp_random_bits() should be used instead.
iconv implementations which do not properly set errno in case of errors are no longer supported.
The unused default_host
argument of imap_headerinfo()
has been removed.
The imap_header() function which is an alias of imap_headerinfo() has been removed.
The deprecated constant INTL_IDNA_VARIANT_2003
has been removed.
移除弃用常量 Normalizer::NONE
。
移除弃用函数 ldap_sort()、ldap_control_paged_result() 和 ldap_control_paged_result_response()。
ldap_set_rebind_proc() 的接口已修改;callback
不再接受空字符串;应该使用 null
代替。
The mbstring.func_overload directive has been
removed. The related MB_OVERLOAD_MAIL
,
MB_OVERLOAD_STRING
, and MB_OVERLOAD_REGEX
constants
have also been removed. Finally, the "func_overload"
and
"func_overload_list"
entries in mb_get_info() have been
removed.
mb_parse_str() can no longer be used without specifying a result array.
A number of deprecated mbregex aliases have been removed. See the following list for which functions should be used instead:
The e
modifier for mb_ereg_replace() has been removed.
mb_ereg_replace_callback() should be used instead.
A non-string pattern argument to mb_ereg_replace() will now be interpreted as a string instead of an ASCII codepoint. The previous behavior may be restored with an explicit call to chr().
The needle
argument for mb_strpos(),
mb_strrpos(), mb_stripos(),
mb_strripos(), mb_strstr(),
mb_stristr(), mb_strrchr() and
mb_strrichr() can now be empty.
The is_hex
parameter, which was not used internally, has been removed from
mb_decode_numericentity().
The legacy behavior of passing the encoding as the third argument instead of an offset for the
mb_strrpos() function has been removed; an explicit 0
offset with the encoding should be provided as the fourth argument instead.
The ISO_8859-*
character encoding aliases have been replaced by
ISO8859-*
aliases for better interoperability with the iconv extension. The
mbregex ISO 8859 aliases with underscores (ISO_8859_*
and
ISO8859_*
) have also been removed.
mb_ereg() and mb_eregi() will now return boolean true
on
a successful match. Previously they returned integer 1
if
matches
was not passed, or max(1, strlen($matches[0]))
if
matches
was passed.
The OCI-Lob class is now called OCILob, and the OCI-Collection class is now called OCICollection for name compliance enforced by PHP 8 arginfo type annotation tooling.
Several alias functions have been marked as deprecated.
oci_internal_debug() and its alias ociinternaldebug() have been removed.
odbc_connect() no longer reuses connections.
The unused flags
parameter of odbc_exec() has been
removed.
openssl_seal() and openssl_open() now require
method
to be passed, as the previous default of "RC4"
is considered insecure.
When passing invalid escape sequences they are no longer interpreted as literals. This behavior
previously required the X
modifier - which is now ignored.
The default error handling mode has been changed from "silent" to "exceptions". See Errors and error handling for details.
The signatures of some PDO methods have changed:
PDO::query(string $query, ?int $fetchMode = null, mixed ...$fetchModeArgs)
PDOStatement::setFetchMode(int $mode, mixed ...$args)
The php.ini directive pdo_odbc.db2_instance_name has been removed.
PDO::inTransaction() now reports the actual transaction state of
the connection, rather than an approximation maintained by PDO. If a query that is
subject to "implicit commit" is executed, PDO::inTransaction()
will subsequently return false
, as a transaction is no longer active.
The deprecated pg_connect() syntax using multiple parameters instead of a connection string is no longer supported.
The deprecated pg_lo_import() and pg_lo_export() signature that passes the connection as the last argument is no longer supported. The connection should be passed as first argument instead.
pg_fetch_all() will now return an empty array instead of false
for result
sets with zero rows.
Metadata associated with a phar will no longer be automatically unserialized, to fix potential security vulnerabilities due to object instantiation, autoloading, etc.
The method signatures
ReflectionClass::newInstance($args)
ReflectionFunction::invoke($args)
ReflectionMethod::invoke($object, $args)
have been changed to:
ReflectionClass::newInstance(...$args)
ReflectionFunction::invoke(...$args)
ReflectionMethod::invoke($object, ...$args)
Code that must be compatible with both PHP 7 and PHP 8 can use the following signatures to be compatible with both versions:
ReflectionClass::newInstance($arg = null, ...$args)
ReflectionFunction::invoke($arg = null, ...$args)
ReflectionMethod::invoke($object, $arg = null, ...$args)
The ReflectionType::__toString() method will now return a complete debug representation of the type, and is no longer deprecated. In particular the result will include a nullability indicator for nullable types. The format of the return value is not stable and may change between PHP versions.
Reflection export() methods have been removed. Instead reflection objects can be cast to string.
ReflectionMethod::isConstructor() and
ReflectionMethod::isDestructor() now also return true
for
__construct() and
__destruct() methods of interfaces.
Previously, this would only be true for methods of classes and traits.
ReflectionType::isBuiltin() method has been moved to ReflectionNamedType. ReflectionUnionType does not have it.
The deprecated AI_IDN_ALLOW_UNASSIGNED
and
AI_IDN_USE_STD3_ASCII_RULES
flags
for
socket_addrinfo_lookup() have been removed.
SplFileObject::fgetss() has been removed.
SplFileObject::seek() 总是寻找到一行的开头。之前,位置 >=1
会搜索到下一行的开头。
SplHeap::compare() now specifies a method signature. Inheriting classes implementing this method will now have to use a compatible method signature.
SplDoublyLinkedList::push(),
SplDoublyLinkedList::unshift() and
SplQueue::enqueue() now return void instead of true
.
spl_autoload_register() will now always throw a
TypeError on invalid arguments, therefore the second argument
do_throw
is ignored and a notice will be emitted if it is set to false
.
SplFixedArray is now an IteratorAggregate and not an Iterator. SplFixedArray::rewind(), SplFixedArray::current(), SplFixedArray::key(), SplFixedArray::next(), and SplFixedArray::valid() have been removed. In their place, SplFixedArray::getIterator() has been added. Any code which uses explicit iteration over SplFixedArray must now obtain an Iterator through SplFixedArray::getIterator(). This means that SplFixedArray is now safe to use in nested loops.
assert() will no longer evaluate string arguments, instead they will be
treated like any other argument. assert($a == $b)
should be used instead of
assert('$a == $b')
. The assert.quiet_eval ini directive and the
ASSERT_QUIET_EVAL
constant have also been removed, as they would no longer
have any effect.
parse_str() can no longer be used without specifying a result array.
The string.strip_tags filter has been removed.
The needle
argument of strpos(),
strrpos(), stripos(), strripos(),
strstr(), strchr(), strrchr(), and
stristr() will now always be interpreted as a string. Previously non-string
needles were interpreted as an ASCII code point. An explicit call to chr() can
be used to restore the previous behavior.
The needle
argument for strpos(),
strrpos(), stripos(), strripos(),
strstr(), stristr() and strrchr() can
now be empty.
The length
argument for substr(),
substr_count(), substr_compare(), and
iconv_substr() can now be null
. null
values will behave as if no length
argument was provided and will therefore return the remainder of the string instead of an empty
string.
The length
argument for array_splice() can now be
null
. null
values will behave identically to omitting the argument, thus removing everything
from the offset
to the end of the array.
The args
argument of vsprintf(),
vfprintf(), and vprintf() must now be an array. Previously
any type was accepted.
The 'salt'
option of password_hash() is no longer
supported. If the 'salt'
option is used a warning is generated, the provided
salt is ignored, and a generated salt is used instead.
The quotemeta() function will now return an empty string if an empty string
was passed. Previously false
was returned.
The following functions have been removed:
FILTER_SANITIZE_MAGIC_QUOTES
has been removed.
Calling implode() with parameters in a reverse order ($pieces,
$glue)
is no longer supported.
parse_url() will now distinguish absent and empty queries and fragments:
http://example.com/foo → query = null, fragment = null
http://example.com/foo? → query = "", fragment = null
http://example.com/foo# → query = null, fragment = ""
http://example.com/foo?# → query = "", fragment = ""
null
.
var_dump() and debug_zval_dump() will now print floating-point numbers using serialize_precision rather than precision. In a default configuration, this means that floating-point numbers are now printed with full accuracy by these debugging functions.
If the array returned by __sleep() contains non-existing
properties, these are now silently ignored. Previously, such properties would have been
serialized as if they had the value null
.
The default locale on startup is now always "C"
. No locales are inherited from
the environment by default. Previously, LC_ALL
was set to
"C"
, while LC_CTYPE
was inherited from the environment.
However, some functions did not respect the inherited locale without an explicit
setlocale() call. An explicit setlocale() call is now
always required if a locale component should be changed from the default.
The deprecated DES fallback in crypt() has been removed. If an unknown salt
format is passed to crypt(), the function will fail with *0
instead of falling back to a weak DES hash now.
Specifying out of range rounds for SHA256/SHA512 crypt() will now fail with
*0
instead of clamping to the closest limit. This matches glibc behavior.
The result of sorting functions may have changed, if the array contains elements that compare as equal.
Any functions accepting callbacks that are not explicitly specified to accept parameters by reference will now warn if a callback with reference parameters is used. Examples include array_filter() and array_reduce(). This was already the case for most, but not all, functions previously.
The HTTP stream wrapper as used by functions like file_get_contents()
now advertises HTTP/1.1 rather than HTTP/1.0 by default. This does not change the behavior of the
client, but may cause servers to respond differently. To retain the old behavior, set the
'protocol_version'
stream context option, e.g.
<?php
$ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
echo file_get_contents('http://example.org', false, $ctx);
?>
Calling crypt() without an explicit salt is no longer supported. If you would like to produce a strong hash with an auto-generated salt, use password_hash() instead.
substr(), mb_substr(), iconv_substr() and
grapheme_substr() now consistently clamp out-of-bounds offsets to the string
boundary. Previously, false
was returned instead of the empty string in some cases.
On Windows, the program execution functions (proc_open(), exec(), popen() etc.) using the shell, now consistently execute %comspec% /s /c "$commandline", which has the same effect as executing $commandline (without additional quotes).
sem_get() 的 auto_release
参数已从接受 int
更改为接受 bool。
从 tidy_repair_string() 中删除内部未使用的
use_include_path
参数。
tidy::repairString() 和 tidy::repairFile() 成为静态方法。
T_COMMENT
记号将不再包含尾随的换行符。换行符将成为以下 T_WHITESPACE
记号的一部分。需要注意的是,T_COMMENT
后面并不总是跟空格,也可能跟着
T_CLOSE_TAG
或者文件结尾。
命名空间名称现在使用 T_NAME_QUALIFIED
(Foo\Bar
)、T_NAME_FULLY_QUALIFIED
(\Foo\Bar
)
和 T_NAME_RELATIVE
(namespace\Foo\Bar
)记号表示。
T_NS_SEPARATOR
is only used for standalone namespace separators, and only
syntactially valid in conjunction with group use declarations.
XMLReader::open() 和 XMLReader::xml() 现在是静态方法。也可以作为实例方法调用,但如果继承类需要覆盖这些方法,要声明为 static。
XML-RPC 扩展已移动到 PECL,不再是 PHP 发行版的一部分。
ZipArchive::OPSYS_Z_CPM
已移除(名字错误)。使用
ZipArchive::OPSYS_CPM
代替。
gzgetss() 已移除。
zlib.output_compression 不再对
Content-Type: image/*
自动禁用。
测试运行器从 run-test.php 重命名为 run-tests.php,以匹配其在 php-src 中的名字。