不向后兼容的变更

PHP 内核

$GLOBALS 访问限制

现在访问 $GLOBALS 数组受到一些限制。 对单个数组元素的读写访问 $GLOBALS['var'] 与之前一样。 也将继续支持对整个数组 $GLOBALS 的只读访问。 但是,不再支持对整个 $GLOBALS 数组的写访问。 例如,array_pop($GLOBALS) 将返回错误。

在继承的方法中 static 变量的用法

当一个方法使用继承的(而不是重写的)静态变量时,继承的方法将与父级共享这个静态变量。

<?php
class A {
public static function
counter() {
static
$counter = 0;
$counter++;
return
$counter;
}
}
class
B extends A {}
var_dump(A::counter()); // int(1)
var_dump(A::counter()); // int(2)
var_dump(B::counter()); // int(3),之前是 int(1)
var_dump(B::counter()); // int(4),之前是 int(2)
?>
这意味着方法中的静态变量现在的使用方式与静态属性一样。

在强制参数之前指定可选参数

现在在强制参数之前指定可选参数都被视为强制参数,即使是使用命名参数调用也是如此。自 PHP 8.0.0 起至 PHP 8.1.0 之前,在定义时会发出弃用通知,但能成功调用。自 PHP 8.1.0 起,会抛出类为 ArgumentCountError 的错误,就跟使用位置参数调用一样。

<?php
function makeyogurt($container = "bowl", $flavour)
{
return
"Making a $container of $flavour yogurt.\n";
}
try
{
echo
makeyogurt(flavour: "raspberry");
}
catch (
Error $e)
{
echo
get_class($e), ' - ', $e->getMessage(), "\n";
}
?>

以上例程在 PHP 8.0 中的输出:

Deprecated: Required parameter $flavour follows optional parameter $container
 in example.php on line 3
Making a bowl of raspberry yogurt.

以上例程在 PHP 8.1 中的输出:

Deprecated: Optional parameter $container declared before required parameter
 $flavour is implicitly treated as a required parameter in example.php on line 3
ArgumentCountError - makeyogurt(): Argument #1 ($container) not passed

Note that a default value of null can be used before required parameters to specify a nullable type, but the parameter will still be required.

返回类型与内部类的兼容性

大多数非 Final 的内部方法现在要求重写方法声明一个可兼容的返回类型,否则在继承时会给出方法废弃的提示。 如果由于 PHP 跨版本兼容性的问题,导致不能为重写方法声明返回类型,则可以添加 ReturnTypeWillChange 注解来取消废弃提示。

新的关键词

现在 readonly 是一个关键词。不过,它仍然可以被用作函数名。

never 现在是保留字,所以不能用于类,接口或者 trait,也禁止在命名空间中使用。

Resource 类型迁移为 Object 类型

一些 资源(resource) 类型已被迁移到 object 类型。 要检查返回值,应该从 is_resource() 检查是否为资源,更改为检查返回值是否等于 false

MySQLi

现在 mysqli_fetch_fields()mysqli_fetch_field_direct() 对于 max_length 将返回 0 值。 这一信息可以迭代结果集来计算,并获取最大长度。这是之前 PHP 内部的做法。

常量 MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH 不再生效。

常量 MYSQLI_STORE_RESULT_COPY_DATA 不再生效。 传递给 mysqli::store_result()mode 参数的所有值不再生效。

现在 mysqli::connect() 成功时返回 true 而不再返回 null

默认错误处理模式已经由 silent 变成了 exceptions,更多详情及如何设置该属性请参见 MySQLi reporting mode 。 要恢复之前的行为习惯,请使用: mysqli_report(MYSQLI_REPORT_OFF);

现在,扩展 mysqli_stmt::execute() 类需要指定额外的可选参数。

MySQLnd

mysqlnd.fetch_data_copy INI 指令已被取消。 这不会造成用户可见的变化。

OpenSSL

现在 EC 私钥将以 PKCS#8 格式导出,而非像其他秘钥那样的传统格式。

现在 openssl_pkcs7_encrypt()openssl_cms_encrypt() 将默认使用 AES-128-CBC,而非 RC2-40。 RC2-40 加密被认为是不安全的,OpenSSL 3 默认不启用。

PHP 数据对象

现在 PDO::ATTR_STRINGIFY_FETCHES 的类型从 bool 变成了字符串 "0""1"。之前的 bool 类型没有被字符串化。

现在当 PDO::ATTR_STRINGIFY_FETCHES 被禁用时, 以 PDO::PARAM_LOB 为参数调用 PDOStatement::bindColumn() 结果将总是绑定一个流。 以前,结果要么是一个流,要么是一个字符串,这取决于所用的数据库驱动及其执行的时间。

MySQL 驱动

现在,当使用模拟预处理时,结果集中的整数及浮点数将会以 PHP 原始类型返回,而不是以 string 类型返回。 这与原生的预处理方式一样。 之前的行为方式可以通过 PDO::ATTR_STRINGIFY_FETCHES 恢复。

SQLite 驱动

现在,结果集中的整数及浮点数将会以 PHP 原始类型返回。 之前的行为方式可以通过 PDO::ATTR_STRINGIFY_FETCHES 恢复。

Phar

为了遵守 ArrayAccess 接口, Phar::offsetUnset()PharData::offsetUnset() 不再以 bool 类型返回。

Standard

version_compare() 函数不再接收未经记录的操作符缩写。

现在 htmlspecialchars()htmlentities()htmlspecialchars_decode()html_entity_decode()get_html_translation_table() 使用 ENT_QUOTES | ENT_SUBSTITUTE 作为默认值,而不再是 ENT_COMPAT。 这意味着 ' 被转义为 &#039; 而不像之前那样不作处理。 此外,有缺陷的 UTF-8 将被 Unicode 替代字符(substitute character)替换,而不是产生一个空字符串。

现在 debug_zval_dump() 函数可以打印封装的引用计数了,不仅仅只是打印 & 引用计数的值。 这更准确地模拟了自 PHP 7.0 以来的引用注解。

现在 debug_zval_dump() 可打印 interned 字符串,而不是 interned 字符串和不可变数组的虚拟的引用计数。

PHP 标准库(SPL)

SplFixedArray 将会像 array 类型一样被 JSON 编码。

add a note

User Contributed Notes

There are no user contributed notes for this page.
To Top