PHP Velho Oeste 2024

不向后兼容的变更

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

注意,在强制参数之前可以使用 null 默认值来指定可为空类型,但仍然需要该参数。

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

大多数非 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 变成了 exception,更多详情及如何设置该属性请参见 MySQLi 报告模式。要恢复之前的行为习惯,请使用: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 原始类型返回,而不是字符串。这与原生的预处理方式一样。之前的行为方式可以通过 PDO::ATTR_STRINGIFY_FETCHES 恢复。

SQLite 驱动

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

Phar

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

常规

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