PHP 8.0.x


  • 提升性能
    • 基于缓存前置思想,使用CPU机器码缓存,绕过Zend VM及其过程开销来尽可能提升性能
      • JIT

从 PHP 7.4.x 移植到 PHP 8.0.x

PHP 8.0: What’s New and Changed
PHP Manual


PHP Core

  • 字符串与数字的比较

    • v8.0.0 数字与非数字形式的字符串之间的非严格比较现在将首先将数字转为字符串,然后比较这两个字符串。 数字与数字形式的字符串之间的比较仍然像之前那样进行。 请注意,这意味着 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
  • v8.0.0 match 现在是一个保留字。

    PHP RFC: Match expression v2

  • v8.0.0 断言(Assertion)失败现在默认抛出异常。如果想要改回之前的行为,可以在 INI 设置中设置 assert.exception=0

  • 8.0.0 与类名相同的方法名将不再被当做构造方法。应该使用__construct() 来取代它。

  • 8.0.0 不再允许通过静态调用的方式去调用非静态方法。因此is_callable()在检查一个类名与非静态方法 时将返回失败(应当检查一个类的实例)。

  • v8.0.0 (real)(unset) 转换已被移除。

  • v8.0.0 The track_errors ini directive has been removed. This means that php_errormsg is no longer available. The error_get_last() function may be used instead.

  • v8.0.0 The ability to define case-insensitive constants has been removed. The third argument to define() may no longer be true.

  • v8.0.0 The ability to specify an autoloader using an __autoload() function has been removed. spl_autoload_register() should be used instead.

  • v8.0.0 The errcontext argument will no longer be passed to custom error handlers set with set_error_handler().

  • v8.0.0 create_function() has been removed. Anonymous functions may be used instead.

  • v8.0.0 each() has been removed. foreach or ArrayIterator should be used instead.

  • v8.0.0 The ability to unbind this from closures that were created from a method, using Closure::fromCallable() or ReflectionMethod::getClosure(), has been removed.

  • v8.0.0 The ability to unbind this from proper closures that contain uses of this has also been removed.

  • v8.0.0 The ability to use array_key_exists() with objects has been removed. isset() or property_exists() may be used instead.

  • v8.0.0 The behavior of array_key_exists() regarding the type of the key parameter has been made consistent with isset() and normal array access. All key types now use the usual coercions and array/object keys throw a TypeError.

  • v8.0.0 Any array that has a number n as its first numeric key will use n+1 for its next implicit key, even if n is negative.

    PHP RFC: Arrays starting with a negative index
    PHP 8.0: Implicit negative array key increments do not skip negative numbers

  • v8.0.0 The default error_reporting level is now E_ALL. Previously it excluded E_NOTICE and E_DEPRECATED.

  • v8.0.0 display_startup_errors is now enabled by default.

  • v8.0.0 Using parent inside a class that has no parent will now result in a fatal compile-time error.

  • v8.0.0 The @ operator will no longer silence fatal errors (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE). Error handlers that expect error_reporting to be 0 when @ is used, should be adjusted to use a mask check instead:

    // Replace
    function my_error_handler($err_no, $err_msg, $filename, $linenum) {
        if (error_reporting() == 0) {
            return false; // Silenced
        // ...
    // With
    function my_error_handler($err_no, $err_msg, $filename, $linenum) {
        if (!(error_reporting() & $err_no)) {
            return false; // Silenced
        // ...

    Additionally, care should be taken that error messages are not displayed in production environments, which can result in information leaks. Please ensure that display_errors=Off is used in conjunction with error logging.

    PHP 8.0: @ Error Suppression operator does not silent fatal errors

  • v8.0.0 #[ is no longer interpreted as the start of a comment, as this syntax is now used for attributes.

    PHP RFC: Attributes v2
    Discussion: Attributes v2
    PHP 8.0: Attributes

  • v8.0.0 Inheritance errors due to incompatible method signatures (LSP violations) will now always generate a fatal error. Previously a warning was generated in some cases.

    PHP RFC: Always generate fatal error for incompatible method signatures
    Github Pull Request: Always generate fatal error for LSP failures #4000
    PHP 8.0: Fatal errors on incompatible method signatures

  • v7.4.0 The precedence of the concatenation operator has changed relative to bitshifts and addition as well as subtraction.

    echo "Sum: " . $a + $b;
    // was previously interpreted as:
    echo ("Sum: " . $a) + $b;
    // is now interpreted as:
    echo "Sum:" . ($a + $b);

    PHP RFC: Change the precedence of the concatenation operator
    PHP 8.0: +/- operators take higher precedence when used with concat (.) operator

  • v8.0.0 Arguments with a default value that resolves to null at runtime will no longer implicitly mark the argument type as nullable. Either an explicit nullable type, or an explicit null default value has to be used instead.

    // Replace
    function test(int $arg = CONST_RESOLVING_TO_NULL) {}
    // With
    function test(?int $arg = CONST_RESOLVING_TO_NULL) {}
    // Or
    function test(int $arg = null) {}

    Github Pull Request: Don’t make argument nullable based on AST null initializer #4720

  • v8.0.0 A number of warnings have been converted into Error exceptions:

    PHP RFC: Reclassifying engine warnings

    • Attempting to write to a property of a non-object. Previously this implicitly created an stdClass object for null, false and empty strings.
    • Attempting to append an element to an array for which the PHP_INT_MAX key is already used.
    • Attempting to use an invalid type (array or object) as an array key or string offset.
    • Attempting to write to an array index of a scalar value.
    • Attempting to unpack a non-array/Traversable.
    • Attempting to access unqualified constants which are undefined. Previously, unqualified constant accesses resulted in a warning and were interpreted as strings.

    A number of notices have been converted into warnings:

    • Attempting to read an undefined variable.
    • Attempting to read an undefined property.
    • Attempting to read an undefined array key.
    • Attempting to read a property of a non-object.
    • Attempting to access an array index of a non-array.
    • Attempting to convert an array to string.
    • Attempting to use a resource as an array key.
    • Attempting to use null, a boolean, or a float as a string offset.
    • Attempting to read an out-of-bounds string offset.
    • Attempting to assign an empty string to a string offset.
  • v8.0.0 Attempting to assign multiple bytes to a string offset will now emit a warning.

  • v8.0.0 Unexpected characters in source files (such as NUL bytes outside of strings) will now result in a ParseError exception instead of a compile warning.

    Github Pull Request: Replace “unexpected character” warning with ParseError #4767

  • v8.0.0 Uncaught exceptions now go through “clean shutdown”, which means that destructors will be called after an uncaught exception.

  • v8.0.0 The compile time fatal error “Only variables can be passed by reference” has been delayed until runtime, and converted into an “Argument cannot be passed by reference” Error exception.

  • v8.0.0 Some “Only variables should be passed by reference” notices have been converted to “Argument cannot be passed by reference” exception.

  • v8.0.0 The generated name for anonymous classes has changed. It will now include the name of the first parent or interface:

    new class extends ParentClass {};
    // -> [email protected]
    new class implements FirstInterface, SecondInterface {};
    // -> [email protected]
    new class {};
    // -> [email protected]

    The name shown above is still followed by a NUL byte and a unique suffix.

    Github Pull Request: Improve generated names for anonymous classes #5153

  • v8.0.0 Non-absolute trait method references in trait alias adaptations are now required to be unambiguous:

    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.

    Github Pull Request: Require non-absolute trait method refs to be unambiguous #5232

  • v8.0.0 The signature of abstract methods defined in traits is now checked against the implementing class method:

    trait MyTrait {
        abstract private function neededByTrait(): string;
    class MyClass {
        use MyTrait;
        // Error, because of return type mismatch.
        private function neededByTrait(): int { return 42; }

    PHP RFC: Validation for abstract trait methods
    Github Pull Request: Check abstract method signatures coming from traits #5068

  • v8.0.0 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.

    Github Pull Request: Completely remove disabled functions from function table #5473

  • v8.0.0 data:// stream wrappers are no longer writable, which matches the documented behavior.

  • v8.0.0 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.

    PHP RFC: Stricter type checks for arithmetic/bitwise operators
    Github Pull Request: Make numeric operations on resources, arrays and objects type errors #5331

  • v8.0.0 Float to string casting will now always behave locale-independently.

    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.

    PHP RFC: Locale-independent float to string cast
    Github Pull Request: Make float to string conversions locale-independent #5224

  • v8.0.0 Support for deprecated curly braces for offset access has been removed.

    // Instead of:
    // Write:

    PHP RFC: Deprecate curly brace syntax for accessing array elements and string offsets
    Github Pull Request: Deprecate curly brace syntax for array/string offset access #4416

  • 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.

  • 如果带有默认值的参数后面跟着一个必要的参数,那么默认值就会无效。这在 PHP 8.0.0 中已被废弃,通常可以通过删除默认值,不影响现有功能:

    function test($a = [], $b) {} // 之前
    function test($a, $b) {}      // 之后

    这条规则的一个例外是 Type $param = null 形式的参数,其中 null 的默认值使得类型隐式为空。这种用法仍然是允许的,但仍建议使用显式可空类型。

    function test(A $a = null, $b) {} // 旧写法,仍可用
    function test(?A $a, $b) {}       // 推荐写法
  • 参数 exclude_disabled 不能设置为 false 来调用 get_defined_functions(),该参数已被废弃,不再起作用。 get_defined_functions() 绝不会再包含禁用的函数。

Resource to Object Migration

Several 资源(resource)s have been migrated to objects. Return value checks using is_resource() should be replaced with checks for false.

COM and .Net (Windows)


  • 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.

  • 现在 CURL 扩展要求 libcurl 版本至少为 7.29.0。

  • 移除了 curl_version() 废弃的参数 version

Date and Time


  • 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:

    • DOMNameList
    • DomImplementationList
    • DOMConfiguration
    • DomError
    • DomErrorHandler
    • DOMImplementationSource
    • DOMLocator
    • DOMUserDataHandler
    • DOMTypeInfo




  • 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.


  • The deprecated functions image2wbmp() has been removed.

  • The deprecated functions png2wbmp() and jpeg2wbmp() have been removed.

  • 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.



  • iconv implementations which do not properly set errno in case of errors are no longer supported.


Internationalization Functions

  • The deprecated constant INTL_IDNA_VARIANT_2003 has been removed.

  • The deprecated Normalizer::NONE constant has been removed.




  • 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.



Regular Expressions (Perl-Compatible)

  • When passing invalid escape sequences they are no longer interpreted as literals. This behavior previously required the X modifier – which is now ignored.

PHP Data Objects (PDO)

  • 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)



  • 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.



  • 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.

  • ReflectionFunction::isDisabled() is deprecated, as it is no longer possible to create a ReflectionFunction for a disabled function. This method now always returns false.

  • ReflectionParameter::getClass(), ReflectionParameter::isArray(), and ReflectionParameter::isCallable() are deprecated. ReflectionParameter::getType() and the ReflectionType APIs should be used instead.


  • The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES flags for socket_addrinfo_lookup() have been removed.

Standard PHP Library (SPL)

Standard Library

  • 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:

    • → query = null, fragment = null
    • → query = "", fragment = null
    • → query = null, fragment = ""
    • → query = "", fragment = ""

    Previously all cases resulted in query and fragment being 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.

    $ctx = stream_context_create(['http' => ['protocol_version' => '1.0']]);
    echo file_get_contents('', 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).

  • Sort comparison functions that return true or false will now throw a deprecation warning, and should be replaced with an implementation that returns an integer less than, equal to, or greater than zero.

    // Replace
    usort($array, fn($a, $b) => $a > $b);
    // With
    usort($array, fn($a, $b) => $a <=> $b);


  • The auto_release parameter of sem_get() was changed to accept bool values rather than int.



  • T_COMMENT tokens will no longer include a trailing newline. The newline will instead be part of a following T_WHITESPACE token. It should be noted that T_COMMENT is not always followed by whitespace, it may also be followed by T_CLOSE_TAG or end-of-file.

  • Namespaced names are now represented using the T_NAME_QUALIFIED (Foo\Bar), T_NAME_FULLY_QUALIFIED (\Foo\Bar) and T_NAME_RELATIVE (namespace\Foo\Bar) tokens. T_NS_SEPARATOR is only used for standalone namespace separators, and only syntactially valid in conjunction with group use declarations.


  • XMLReader::open() and XMLReader::xml() are now static methods. They can still be called as instance methods, but inheriting classes need to declare them as static if they override these methods.


  • The XML-RPC extension has been moved to PECL and is no longer part of the PHP distribution.


  • ZipArchive::OPSYS_Z_CPM has been removed (this name was a typo). Use ZipArchive::OPSYS_CPM instead.

  • Using an empty file as ZipArchive is deprecated. Libzip 1.6.0 does not accept empty files as valid zip archives any longer. The existing workaround will be removed in the next version.

  • The procedural API of Zip is deprecated. Use ZipArchive instead. Iteration over all entries can be accomplished using ZipArchive::statIndex() and a for loop:

    // iterate using the procedural API
    while ($entry = zip_read($zip)) {
        echo zip_entry_name($entry);
    // iterate using the object-oriented API
    assert($zip instanceof ZipArchive);
    for ($i = 0; $entry = $zip->statIndex($i); $i++) {
        echo $entry['name'];


Windows PHP Test Packs

  • The test runner has been renamed from run-test.php to run-tests.php, to match its name in php-src.


  • libxml_disable_entity_loader() has been deprecated. As libxml 2.9.0 is now required, external entity loading is guaranteed to be disabled by default, and this function is no longer needed to protect against XXE attacks, unless the (still vulnerable). LIBXML_NOENT is used. In that case, it is recommended to refactor the code using libxml_set_external_entity_loader() to suppress loading of external entities.


不再支持 EBCDIC targets,虽然它不太可能还在当初的地方继续运行。



PHP Core

  • 新增命名参数的功能。

  • 新增注解的功能。

  • 新增构造器属性提升功能 在构造函数中声明类的属性)。

  • 新增 联合类型

  • 新增 match 表达式

  • 新增Nullsafe 运算符(?->)。

  • 新增 WeakMap 类。

  • 新增 ValueError 类。

  • 现在,只要类型兼容,任意数量的函数参数都可以用一个可变参数替换。 例如允许编写下面的代码:

    class A {
         public function method(int $many, string $parameters, $here) {}
    class B extends A {
         public function method(...$everything) {}
  • static ("后期静态绑定"中) 可以作为返回类型:

    class Test {
         public function create(): static {
              return new static();
  • 现在可以通过 $object::class 获取类名,返回的结果和 get_class($object) 一致。

  • newinstanceof 可用于任何表达式, 用法为 new (expression)(...$args)$obj instanceof (expression)

  • 添加对一些变量语法一致性的修复,例如现在能够编写 Foo::BAR::$baz

  • 添加 Stringable interface, 当一个类定义 __toString() 方法后会自动实现该接口。

  • Trait 可以定义私有抽象方法(abstract private method)。 类必须实现 trait 定义的该方法。

  • 可作为表达式使用 throw。 使得可以编写以下用法:

    $fn = fn() => throw new Exception('Exception in arrow function');
    $user = $session->user ?? throw new Exception('Must have user');
  • 参数列表中的末尾逗号为可选。

    function functionWithLongSignature(
        Type1 $parameter1,
        Type2 $parameter2, // <-- 这个逗号也被允许了
    ) {
  • 现在允许 catch (Exception) 一个 exception 而无需捕获到变量中。

  • 支持 mixed 类型。

  • Private methods declared on a parent class no longer enforce any inheritance rules on the methods of a child class (with the exception of final private constructors). The following example illustrates which restrictions have been removed:

    class ParentClass {
        private function method1() {}
        private function method2() {}
        private static function method3() {}
        // Throws a warning, as "final" no longer has an effect:
        private final function method4() {}
    class ChildClass extends ParentClass {
        // All of the following are now allowed, even though the modifiers aren't
        // the same as for the private methods in the parent class.
        public abstract function method1() {}
        public static function method2() {}
        public function method3() {}
        public function method4() {}
  • get_resource_id() has been added, which returns the same value as (int) $resource. It provides the same functionality under a clearer API.

  • array_slice() 用于没有空隙的数组时, 将不会扫描整个数组去查找开始的位移(offset)。 在 offset 较大、长度较小时,会显著减少函数的运行时间。

  • [<!–swig0–>] 当本地化 LC_CTYPE"C" 时(也是默认值), strtolower() 会使用 SIMD 的实现。

Date and Time


DOMParentNode and DOMChildNode with new traversal and manipulation APIs have been added.


FILTER_VALIDATE_BOOL has been added as an alias for FILTER_VALIDATE_BOOLEAN. The new name is preferred, as it uses the canonical type name.


enchant_dict_add(), enchant_dict_is_added(), and LIBENCHANT_VERSION have been added.


Added a new option pm.status_listen that allows getting the status from different endpoint (e.g. port or UDS file) which is useful for getting the status when all children are busy with serving long running requests.


HashContext objects can now be serialized.

Internationalization Functions

The IntlDateFormatter::RELATIVE_FULL, IntlDateFormatter::RELATIVE_LONG, IntlDateFormatter::RELATIVE_MEDIUM, and IntlDateFormatter::RELATIVE_SHORT constants have been added.


ldap_count_references() has been added, which returns the number of reference messages in a search result.



Added Cryptographic Message Syntax (CMS) (» RFC 5652) support composed of functions for encryption, decryption, signing, verifying and reading. The API is similar to the API for PKCS #7 functions with an addition of new encoding constants: OPENSSL_ENCODING_DER, OPENSSL_ENCODING_SMIME and OPENSSL_ENCODING_PEM:

  • openssl_cms_encrypt() encrypts the message in the file with the certificates and outputs the result to the supplied file.
  • openssl_cms_decrypt() that decrypts the S/MIME message in the file and outputs the results to the supplied file.
  • openssl_cms_read() that exports the CMS file to an array of PEM certificates.
  • openssl_cms_sign() that signs the MIME message in the file with a cert and key and output the result to the supplied file.
  • openssl_cms_verify() that verifies that the data block is intact, the signer is who they say they are, and returns the certs of the signers.

Regular Expressions (Perl-Compatible)

preg_last_error_msg() has been added, which returns a human-readable message for the last PCRE error. It complements preg_last_error(), which returns an integer enum value instead.



SQLite3::setAuthorizer() and respective class constants have been added to set a userland callback that will be used to authorize or not an action on the database.

Standard Library

  • str_contains(), str_starts_with() and str_ends_with() have been added, which check whether haystack contains, starts with or ends with needle, respectively.

  • fdiv() has been added, which performs a floating-point division under IEEE 754 semantics. Division by zero is considered well-defined and will return one of Inf, -Inf or NaN.

  • get_debug_type() has been added, which returns a type useful for error messages. Unlike gettype(), it uses canonical type names, returns class names for objects, and indicates the resource type for resources.

  • printf() and friends now support the %h and %H format specifiers. These are the same as %g and %G, but always use "." as the decimal separator, rather than determining it through the LC_NUMERIC locale.

  • printf() and friends now support using "*" as width or precision, in which case the width/precision is passed as an argument to printf. This also allows using precision -1 with %g, %G, %h and %H. For example, the following code can be used to reproduce PHP’s default floating point formatting:

    printf("%.*H", (int) ini_get("precision"), $float);
    printf("%.*H", (int) ini_get("serialize_precision"), $float);
  • proc_open() now supports pseudo-terminal (PTY) descriptors. The following attaches stdin, stdout and stderr to the same PTY:

    $proc = proc_open($command, [['pty'], ['pty'], ['pty']], $pipes);
  • proc_open() now supports socket pair descriptors. The following attaches a distinct socket pair to stdin, stdout and stderr:

    $proc = proc_open($command, [['socket'], ['socket'], ['socket']], $pipes);

    Unlike pipes, sockets do not suffer from blocking I/O issues on Windows. However, not all programs may work correctly with stdio sockets.

  • Sorting functions are now stable, which means that equal-comparing elements will retain their original order.

  • array_diff(), array_intersect() and their variations can now be used with a single array as argument. This means that usages like the following are now possible:

    // OK even if $excludes is empty:
    array_diff($array, ...$excludes);
    // OK even if $arrays only contains a single array:
  • The flag parameter of ob_implicit_flush() was changed to accept a bool rather than an int.


PhpToken adds an object-based interface to the tokenizer. It provides a more uniform and ergonomic representation, while being more memory efficient and faster.



现在无法禁用 JSON 扩展,将是任意 PHP 版本的内置功能,类似 date 扩展。



现在 SimpleXMLElement 实现(implements)了 RecursiveIterator 并吸收了 SimpleXMLIterator 的功能。 SimpleXMLIteratorSimpleXMLElement 的一个空扩展。

INI 文件处理的变更

  • com.dotnet_version 是一个新的 INI 指令,用于选择 dotnet 对象的 .NET framework 版本。

  • zend.exception_string_param_max_len 是一个新的 INI 指令,用于设置字符串化的调用栈(stack strace)的最大字符串长度。