## 不向下兼容的变更

### PHP 核心

#### Heredoc/Nowdoc 结束标记解释

由于引入了灵活的 heredoc/nowdoc 语法，正文中包含结束标记的文档字符串可能会导致语法错误或解释发生变化。例如在：

    <?php
    $str = <<<FOO
    abcdefg
       FOO
    FOO;
    ?>

`FOO` 缩进在出现之前没有任何特殊含义。现在将解释为 heredoc 字符串的结尾，并且之后的 `FOO;` 将导致语法错误。这个问题始终可以通过选择一个不在字符串内容中出现的标记标签来解决。

#### Switch 中使用 Continue 会发出警告

`switch` 控制流结构使用 `continue` 语句现在将生成警告。在 PHP 中，`continue` 语句相当于 `break`，而在其它语言中它们的行为等同于 `continue 2`。

    <?php
    while ($foo) {
        switch ($bar) {
          case "baz":
             continue;
             // Warning: "continue" targeting switch is equivalent to
             //          "break". Did you mean to use "continue 2"?
       }
    }
    ?>

#### ArrayAccess 上整数 key 的严格解释

类型 `$obj["123"]` 的数组访问，其中 `$obj` 实现了 ArrayAccess 以及 `"123"` 是整数 string 字面量且将不再默默转换为整数，即调用 `$obj->offsetGet("123")` 而不是 `$obj->offsetGet(123)`。这与非字面量的值的现有行为相匹配。数组的行为不会受到任何影响，它们仍然会将整数字符串 key 默默转换为整数。

#### 静态属性将不再通过引用赋值分离

在 PHP 中，静态属性是在继承类之间共享的，除非在子类中明确重写了静态属性。然而，由于实现上的原因，可以通过分配引用来分离静态属性。该漏洞已得到修复。

    <?php
    class Test {
        public static $x = 0;
    }
    class Test2 extends Test { }

    Test2::$x = &$x;
    $x = 1;

    var_dump(Test::$x, Test2::$x);
    // Previously: int(0), int(1)
    // Now:        int(1), int(1)
    ?>

#### 由访问数组和属性返回的引用会立即展开

由访问数组和属性返回的引用现在作为访问的一部分展开（unwrapped）。这意味着在访问和使用访问的值之间，不会再修改引用：

    <?php
    $arr = [1];
    $ref =& $arr[0];
    var_dump($arr[0] + ($arr[0] = 2));
    // 之前：int(4)，现在：int(3)
    ?>

这使得引用和非引用的行为保持一致。请注意，在单个表达式中读取和写入值仍然是未定义的行为，并且将来可能会再次发生变化。

#### 不再支持非整数 key 的可遍历对象的进行参数解包

参数不会解包存在非整数 key 的 Traversable。以下代码在 PHP 5.6-7.2 中意外起作用。

    <?php
    function foo(...$args) {
        var_dump($args);
    }
    function gen() {
        yield 1.23 => 123;
    }
    foo(...gen());
    ?>

#### 杂项

ext_skel 应用程序已重新设计，添加了一些新选项并删除了一些旧选项。现在是用 PHP 编写的，没有外部依赖项。

已弃用对 BeOS 的支持。

由于在 `EH_THROW` 模式下将警告自动转换为异常而引发的异常（例如某些 DateTime 异常）将不再填充 error_get_last() 状态。因此，它们现在的工作方式与手动引发异常相同。

TypeError 现在将错误类型分别报告为 `int` 和 `bool`，而不是 `integer` 和 `boolean`。

未定义变量传递给 compact()，现在将报告为 notice。

getimagesize() 和相关函数现在将 BMP 图像的 mime 类型报告为 `image/bmp` 而不是 `image/x-ms-bmp`，因为前者已经在 IANA 注册（参阅 » RFC 7903）。

stream_socket_get_name() 现在将返回由中括号括起来的 IPv6 地址。例如，将返回 `"[::1]:1337"` 而不是 `"::1:1337"`。

### BCMath 任意精度数学

BCMath 函数抛出的所有警告现在都使用 PHP 的错误处理。以前，一些警告直接写入了 stderr。

现在，bcmul() 和 bcpow() 返回带有指定小数位数的数字。以前，返回的数字可能省略了尾随的小数零。

### IMAP、POP3 和 NNTP

默认情况下禁用 rsh/ssh 登录。使用 imap.enable_insecure_rsh 启用它们。请注意，将邮箱名称传递给 rsh/ssh 命令之前，IMAP 库不会对其进行过滤，因此在启用 rsh/ssh 的情况下将不受信任的数据传递给该函数是不安全的。

### 多字节字符串

由于增加了对命名捕获的支持，使用命名捕获的 `mb_ereg_*()` 模式的行为会有所不同。特别是命名捕获将成为匹配的一部分，并且 mb_ereg_replace() 将说明额外语法。有关详细信息，请参阅命名捕获。

### MySQL 扩展提升

预处理语句现在可以正确报告带有小数位数说明符的 `DATETIME`、`TIME` 和 `TIMESTAMP` 列的带小数的秒（例如，使用微秒时为 `TIMESTAMP(6)`）。以前，返回值中简单地省略了秒的小数部分。

### MySQL 函数（PDO_MYSQL）

预处理语句现在可以正确报告带有小数位数说明符的 `DATETIME`、`TIME` 和 `TIMESTAMP` 列的带小数的秒（例如，使用微秒时为 `TIMESTAMP(6)`）。以前，返回值中简单地省略了秒的小数部分。请注意，这仅影响关闭模拟预处理时 PDO_MYSQL 的使用（例如使用原生预处理功能）。使用具有 `PDO::ATTR_EMULATE_PREPARES`=`true`（默认值）的连接的语句不受已修复错误的影响，并且已经从引擎获取了带正确小数的秒值。

### 反射

反射导出为字符串，现在分别使用 `int` 和 `bool` 而不是 `integer` 和 `boolean`。

### PHP 标准库（SPL）

如果 SPL 自动加载器抛出异常，则不会执行后面的自动加载器。以前，所有自动加载器都会执行，并且会将异常链接起来。

### SimpleXML

涉及 SimpleXML 对象的数学运算现在会将文本视为 int 或 float，以更合适者为准。以前，值会被无条件视为 int。

### 传入 cookie

从 PHP 7.3.23 起，出于安全原因，传入 cookie 的 names 不再进行 url 解码。

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open