PHP Conference Japan 2024

向后不兼容的更改

传递函数参数过少时抛出异常

以前,如果用户定义函数的参数过少,则会发出警告。现在,此警告已提升为 Error 异常。此更改仅适用于用户定义函数,不适用于内部函数。例如

<?php
function test($param){}
test();

以上示例将输出类似以下内容

Fatal error: Uncaught ArgumentCountError: Too few arguments to function test(), 0 passed in %s on line %d and exactly 1 expected in %s:%d

禁止对作用域内省函数进行动态调用

某些函数的动态调用已被禁止(以 $func()array_map('extract', ...) 等形式)。这些函数要么检查或修改另一个作用域,要么存在模棱两可且不可靠的行为。这些函数如下

<?php
(function () {
$func = 'func_num_args';
$func();
})();

以上示例将输出

Warning: Cannot call func_num_args() dynamically in %s on line %d

无效的类、接口和 trait 名称

以下名称不能用于命名类、接口或 trait

数值字符串转换现在尊重科学计数法

数值字符串的整数运算和转换现在尊重科学计数法。这也包括 (int) 类型转换操作,以及以下函数:intval()(其中基数为 10)、settype()decbin()decoct()dechex()

mt_rand() 算法的修复

mt_rand() 现在将默认使用梅森旋转算法的固定版本。如果依赖于 mt_rand() 的确定性输出,则可以使用 MT_RAND_PHP 作为 mt_srand() 的可选第二个参数以保留旧的(不正确的)实现。

rand() 成为 mt_rand() 的别名,srand() 成为 mt_srand() 的别名

rand()srand() 现在已分别成为 mt_rand()mt_srand() 的别名。这意味着以下函数的输出已更改:rand()shuffle()str_shuffle()array_rand()

不允许在标识符中使用 ASCII 删除控制字符

ASCII 删除控制字符(0x7F)不能再用于未加引号的标识符中。

error_logsyslog 值更改

如果 error_log ini 设置设置为 syslog,则 PHP 错误级别将映射到 syslog 错误级别。这与以前的方法相比,在错误日志中提供了更精细的区分,以前的方法仅使用 notice 级别记录所有错误。

不要在不完整的对象上调用析构函数

现在,对于在执行构造函数期间抛出异常的对象,永远不会调用析构函数。在以前的版本中,此行为取决于对象是否在构造函数外部被引用(例如,通过异常回溯)。

call_user_func() 对引用参数的处理

call_user_func() 现在将在调用期望引用作为参数的函数时始终生成警告。以前,这取决于调用是否完全限定。

此外,call_user_func()call_user_func_array() 在这种情况下将不再中止函数调用。“预期引用”警告将发出,但调用将照常进行。

空索引运算符不再支持字符串

将空索引运算符应用于字符串(例如 $str[] = $x)会抛出致命错误,而不是静默转换为数组。

通过空字符串上的字符串索引访问进行赋值

现在,通过字符修改空字符串的方式与非空字符串相同,即写入超出范围的偏移量会用空格填充字符串,其中非整数类型会转换为整数,并且仅使用分配字符串的第一个字符。以前,空字符串会被静默地视为空数组。

<?php
$a
= '';
$a[10] = 'foo';
var_dump($a);
?>

PHP 7.0 中上述示例的输出

array(1) {
  [10]=>
  string(3) "foo"
}

PHP 7.1 中上述示例的输出

string(11) "          f"

已删除的 ini 指令

以下 ini 指令已被删除

  • session.entropy_file
  • session.entropy_length
  • session.hash_function
  • session.hash_bits_per_character

通过引用赋值期间自动创建元素时的数组排序已更改

当这些元素通过引用赋值自动创建时,数组中元素的顺序已更改。例如

<?php
$array
= [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>

PHP 7.0 中上述示例的输出

array(2) {
  ["a"]=>
  &int(1)
  ["b"]=>
  &int(1)
}

PHP 7.1 中上述示例的输出

array(2) {
  ["b"]=>
  &int(1)
  ["a"]=>
  &int(1)
}

相等元素的排序顺序

内部排序算法已得到改进,这可能导致与之前相比,相等元素的排序顺序不同。

注意:

不要依赖相等元素的顺序;它随时可能改变。

E_RECOVERABLE 错误的错误消息

E_RECOVERABLE 错误的错误消息已从“Catchable fatal error”更改为“Recoverable fatal error”。

$options 参数的 unserialize()

unserialize() 函数的 $options 参数中的 allowed_classes 元素现在具有严格类型,即,如果提供的不是 数组布尔值,则 unserialize() 返回 false 并发出 E_WARNING

DateTime 构造函数包含微秒

DateTimeDateTimeImmutable 现在在从当前时间构造时(无论是显式还是使用相对字符串(例如 "first day of next month"))正确地包含微秒。这意味着,两个新创建的实例的简单比较现在更有可能返回 false 而不是 true

<?php
new DateTime() == new DateTime();
?>

致命错误到 Error 异常的转换

在 Date 扩展中,DateTimeDatePeriod 类的无效序列化数据,或从序列化数据中初始化时区失败,现在将从 __wakeup()__set_state() 方法抛出 Error 异常,而不是导致致命错误。

在 DBA 扩展中,数据修改函数(例如 dba_insert())如果键不包含两个元素,现在将抛出 Error 异常,而不是触发可捕获的致命错误。

在 DOM 扩展中,无效的模式或 RelaxNG 验证上下文现在将抛出 Error 异常,而不是导致致命错误。类似地,尝试注册不扩展适当基类的节点类,或尝试读取无效属性或写入只读属性,现在也将抛出 Error 异常。

在 IMAP 扩展中,超过 16385 字节的电子邮件地址将抛出 Error 异常,而不是导致致命错误。

在 Intl 扩展中,在调用父方法之前,如果未在扩展 Collator 的类中调用父构造函数,现在将抛出 Error 而不是导致可恢复的致命错误。此外,克隆 Transliterator 对象在克隆内部转换器失败时现在将抛出 Error 异常,而不是导致致命错误。

在 LDAP 扩展中,为 ldap_batch_modify() 提供未知的修改类型现在将抛出 Error 异常,而不是导致致命错误。

在 mbstring 扩展中,如果提供了无效的 PHP 表达式并且使用了“e”选项,则 mb_ereg()mb_eregi() 函数现在将抛出 ParseError 异常。

在 Mcrypt 扩展中,如果无法初始化 mcrypt,则 mcrypt_encrypt()mcrypt_decrypt() 现在将抛出 Error 异常,而不是导致致命错误。

在 mysqli 扩展中,尝试读取无效属性或写入只读属性现在将抛出 Error 异常,而不是导致致命错误。

在 Reflection 扩展中,无法检索反射对象或检索对象属性现在将抛出 Error 异常,而不是导致致命错误。

在 Session 扩展中,如果自定义会话处理程序未为会话 ID 返回字符串,则当必须生成会话 ID 时,现在将抛出 Error 异常,而不是导致致命错误。

在 SimpleXML 扩展中,创建未命名或重复的属性现在将抛出 Error 异常,而不是导致致命错误。

在 SPL 扩展中,尝试克隆 SplDirectory 对象现在将抛出 Error 异常,而不是导致致命错误。类似地,在迭代对象时调用 ArrayIterator::append() 现在也将抛出 Error 异常。

在标准扩展中,assert() 函数,当其第一个参数提供字符串参数时,如果 PHP 代码无效,现在将抛出 ParseError 异常,而不是导致可捕获的致命错误。类似地,在类范围之外调用 forward_static_call() 现在将抛出 Error 异常。

在 Tidy 扩展中,手动创建 tidyNode 现在将抛出 Error 异常,而不是导致致命错误。

在 WDDX 扩展中,序列化时的循环引用现在将抛出 Error 异常,而不是导致致命错误。

在 XML-RPC 扩展中,序列化时的循环引用现在将抛出 Error 异常的实例,而不是导致致命错误。

在 Zip 扩展中,如果 glob 支持不可用,则 ZipArchive::addGlob() 方法现在将抛出 Error 异常,而不是导致致命错误。

词法绑定的变量不能重用名称

通过 use 结构绑定到 闭包 的变量不能使用与任何 超级全局变量$this 或任何参数相同的名称。例如,所有这些函数定义都将导致致命错误。

<?php
$f
= function () use ($_SERVER) {};
$f = function () use ($this) {};
$f = function ($param) use ($param) {};

long2ip() 参数类型更改

long2ip() 现在期望一个 整数 而不是 字符串

JSON 编码和解码

现在,serialize_precision ini 设置控制编码 浮点数 时的序列化精度。

解码空键现在会导致空属性名,而不是 _empty_ 作为属性名。

<?php
var_dump
(json_decode(json_encode(['' => 1])));

以上示例将输出类似以下内容

object(stdClass)#1 (1) {
  [""]=>
  int(1)
}

当为 json_encode() 提供 JSON_UNESCAPED_UNICODE 标志时,现在将转义序列 U+2028 和 U+2029。

mb_ereg()mb_eregi() 参数语义的更改

mb_ereg()mb_eregi() 函数的第三个参数 (regs) 如果没有匹配到任何内容,现在将被设置为一个空数组。以前,该参数不会被修改。

放弃对 sslv2 流的支持

sslv2 流现在已在 OpenSSL 中删除。

在编译时禁止已键入返回的“return; ”

在声明返回类型的函数中,不带参数的 return 语句现在会触发 E_COMPILE_ERROR(除非返回类型声明为 void),即使永远不会到达 return 语句。

添加注释

用户贡献的注释 5 条注释

love at sickpeople dot se
8 年前
对于从 5.x 迁移到 7.1 的任何人

关于此页面上的“当元素在通过引用赋值期间自动创建时,数组排序已更改”

(https://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.array-order)

7.1 的行为与 PHP 5 相同。只有 7.0 不同。

参见 https://3v4l.org/frbUc

<?php

$array
= [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
kees at twekaers dot net
7 年前

向后不兼容的更改“字符串不再支持空索引运算符”的影响远不止在以下代码中导致致命错误。

<?php
$a
= "";
$a[] = "hello world";
var_dump($a);
?>

这将在 7.1 中导致致命错误,但在 7.0 或更低版本中将按预期工作并给出:(无通知,无警告)

array(1) {
[0]=>
string(11) "hello world"
}

但是,以下内容也发生了更改

<?php
$a
= "";
$a[0] = "hello world";
var_dump($a);
// 7.1: string(1) "h"
// pre-7.1: array(1) { [0]=> string(11) "hello world" }

$a = "";
$a[5] = "hello world";
var_dump($a);
// 7.1: string(6) " h"
// pre-7.1: array(1) { [0]=> string(11) "hello world" }

?>
m dot r dot sopacua at gmail dot com
7 年前

"我的天哪!为什么删除了 session.hash_function?!伙计!"

https://wiki.php.net/rfc/session-id-without-hashing

搞定。帮你省了一次搜索。
mikem at gmail dot com
7 年前

ArgumentCountError - 此修改是避免在旧项目中使用此版本的首要原因。
david at artefactual dot com
5 年前
关于 ArgumentCountError,PHP 7.1+ 仍然支持使用可变数量参数的用户函数,使用“func(...$args) {}”语法,请参阅:https://php.net/manual/en/functions.arguments.php#functions.variable-arg-list
To Top