现在访问 $GLOBALS 数组受到一些限制。对单个数组元素的读写访问
$GLOBALS['var']
与之前一样。也将继续支持对整个数组
$GLOBALS 的只读访问。但是,不再支持对整个
$GLOBALS 数组的写访问。例如
array_pop($GLOBALS)
将返回错误。
当一个方法使用继承的(而不是重写的)静态变量时,继承的方法将与父级共享这个静态变量。
<?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 类型。要检查返回值,应该从 is_resource()
检查是否为资源,更改为检查返回值是否等于 false
。
现在 FTP 函数接收并返回 FTP\Connection
对象类型,而不是 ftp
resource 类型。
现在 IMAP 函数接收并返回 IMAP\Connection
对象类型,而不是 imap
resource 类型。
现在 LDAP 函数接收并返回 LDAP\Connection
对象类型,而不是 ldap link
resource 类型。
现在 LDAP 函数接收并返回 LDAP\Result
对象类型,而不是 ldap result
resource 类型。
现在 LDAP 函数接收并返回 LDAP\ResultEntry
对象类型,而不是 ldap result entry
resource 类型。
现在 PgSQL 函数接收并返回 PgSql\Connection
对象类型,而不是 pgsql link
resource 类型。
现在 PgSQL 函数接收并返回 PgSql\Result
对象类型,而不是 pgsql result
resource 类型。
现在 PgSQL 函数接收并返回 PgSql\Lob
对象类型,而不是 pgsql large object
resource 类型。
现在 PSpell 函数接收并返回 PSpell\Dictionary
对象类型,而不是 pspell
resource 类型。
现在 PSpell 函数接收并返回 PSpell\Config
对象类型,而不是 pspell config
resource 类型。
现在 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.fetch_data_copy INI 指令已被取消。这不会造成用户可见的变化。
现在 EC 私钥将以 PKCS#8 格式导出,而非像其他秘钥那样的传统格式。
现在 openssl_pkcs7_encrypt() 和 openssl_cms_encrypt() 将默认使用 AES-128-CBC,而非 RC2-40。RC2-40 加密被认为是不安全的,OpenSSL 3 默认不启用。
现在 PDO::ATTR_STRINGIFY_FETCHES
的类型从 bool 变成了字符串 "0"
或
"1"
。之前的 bool 类型没有被字符串化。
现在当 PDO::ATTR_STRINGIFY_FETCHES
未启用时,以 PDO::PARAM_LOB
为参数调用
PDOStatement::bindColumn() 结果将始终绑定流。以前,结果是流或字符串,这取决于所用的数据库驱动及其执行绑定的时间。
现在,当使用模拟预处理时,结果集里面的整数及浮点数将会以 PHP 原始类型返回,而不是字符串。这与原生的预处理方式一样。之前的行为方式可以通过
PDO::ATTR_STRINGIFY_FETCHES
恢复。
现在,结果集中的整数及浮点数将会以 PHP 原始类型返回。之前的行为方式可以通过 PDO::ATTR_STRINGIFY_FETCHES
恢复。
为了遵守 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
。这意味着
'
被转义为 '
而不像之前那样不作处理。此外,有缺陷的
UTF-8 将被 Unicode 替代字符(substitute character)替换,而不是产生一个空字符串。
现在 debug_zval_dump() 函数可以打印封装的引用计数了,不仅仅只是打印 &
引用计数的值。这更准确地模拟了自 PHP 7.0 以来的引用注解。
现在 debug_zval_dump() 可打印 interned
字符串,而不是 interned 字符串和不可变数组的虚拟的引用计数。
SplFixedArray 将会像 array 类型一样被 JSON 编码。