不向后兼容的变更
当传递参数过少时将抛出错误
在过去如果我们调用一个用户定义的函数时,提供的参数不足,那么将会产生警告(warning)。现在,这个警告被提升为错误异常(Error exception)。这个变更仅对用户定义的函数生效,并不包含内置函数。例如:
<?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
禁止动态调用作用域内的内省(introspection)函数
禁止动态调用($func()
或 array_map('extract', ...)
的形式等)某些函数。这些函数会检查或修改另一个作用域,并呈现出不明确且不可靠的行为。函数如下:
- assert()——字符串作为第一个参数
- compact()
- extract()
- func_get_args()
- func_get_arg()
- func_num_args()
- get_defined_vars()
- mb_parse_str()——使用一个参数
- parse_str()——使用一个参数
<?php
(function () {
$func = 'func_num_args';
$func();
})();
以上示例会输出:
Warning: Cannot call func_num_args() dynamically in %s on line %d
数字字符串转换现在遵循科学记数法
现在在数字字符串上执行整数运算和转换会考虑科学计数法。这还包括 (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_log
更改为 syslog
值
如果 error_log
ini 设置为 syslog
,PHP 错误等级会映射到 syslog
错误级别。这在错误日志中带来了更好的区分,与之前相反,之前所有的错误只记录了错误级别。
在不完整的对象上不再调用析构方法
对于在执行构造方法时抛出异常的对象,现在析构方法绝不会被调用。在先前的版本中,这个行为取决于对象是否在构造方法以外的地方呗引用(例如一个错误堆栈回溯)
call_user_func() 不再支持对传址的函数的调用
call_user_func() 现在在调用一个以引用作为参数的函数时将始终产生一个警告。先前这取决于这个调用行为是否完全符合条件。
此外,call_user_func() 和 call_user_func_array() 在这种情况下将不再中断函数调用。现在会出现包含“expected reference”的警告信息,但函数调用将正常进行。
字符串不再支持空索引操作符
对字符串使用一个空索引操作符(例如$str[] = $x
)将会抛出一个致命错误,而不是静默地将其转为一个数组。
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 错误的错误消息已从“可捕获的致命错误”更改为“可恢复的致命错误”。
unserialize() 的 $options 参数
unserialize() 的 $options 参数的 allowed_classes
元素现在是严格类型,也就是说,如果指定了 array 或 bool 以外的任何内容,则
unserialize() 返回 false
并发出 E_WARNING
。
DateTime 构造方法包含微秒
DateTime 和 DateTimeImmutable
现在构造当前时间时正确地包含微秒,无论是明确指定的还是使用相对字符串(例如 "first day of next
month"
)。这意味着两个新创建的实例的原生比较现在更有可能返回 false
而不是 true
:
<?php
new DateTime() == new DateTime();
?>
核心错误转换为 Error 异常
在 Date 扩展中,DateTime 或 DatePeriod 类的无效序列化数据或者序列化数据的时区初始化失败,现在将从 __wakeup() 或 __set_state() 方法抛出 Error 异常,而不是导致致命错误。
在 DBA 扩展中,如果键没有完全包含两个元素,数据修改函数(例如 dba_insert())现在将抛出 Error 异常,而不是触发可捕获的致命错误。
在 DOM 扩展中,无效的模式或 RelaxNG 验证上下文现在将引发 Error 异常,而不是导致致命错误。同样,尝试注册不继承适宜基类的节点类、尝试读取无效属性或写入只读属性,现在也将引发 Error 异常。
在 IMAP 扩展中,长度超过 16385 字节的电子邮件地址将引发 Error 异常,而不是导致致命错误。
在 Intl 扩展中,在调用父级方法之前,在继承 Collator 的类中调用父级构造方法失败,现在将抛出 Error 而不是可恢复的致命错误。此外克隆 Transliterator 对象时,如果无法克隆内部 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() 函数现在将抛出 ParseError 异常,而不是在 PHP 代码无效时导致可捕获的致命错误。同理,在类作用域之外调用 forward_static_call() 现在将引发 Error 异常。
在 Tidy 扩展中,手动创建 tidyNode 现在将抛出 Error 异常,而不是导致致命错误。
在 WDDX 扩展中,序列化时的循环引用现在将引发 Error 异常,而不是导致致命错误。
在 XML-RPC 扩展中,序列化时的循环引用现在将抛出 Error 异常实例,而不是导致致命错误。
在 Zip 扩展中,如果 glob 支持无效,ZipArchive::addGlob() 方法现在将引发 Error 异常,而不是导致致命错误。
词法绑定变量不能重用名字
通过 use
构造绑定到 closure
的变量不能使用与任何 superglobals、$this 或任何参数相同的名称。例如,所有这些函数定义都会导致致命错误:
<?php
$f = function () use ($_SERVER) {};
$f = function () use ($this) {};
$f = function ($param) use ($param) {};
JSON 编/解码
serialize_precision
ini 设置现在控制编码 float 时的序列化精度。
解码空键(empty key)现在会产生空属性,而不是 _empty_
作为属性名称。
<?php
var_dump(json_decode(json_encode(['' => 1])));
以上示例的输出类似于:
object(stdClass)#1 (1) { [""]=> int(1) }
当向 json_encode() 提供 JSON_UNESCAPED_UNICODE
flag 时,现在转义序列 U+2028 和 U+2029。
更改 mb_ereg() 和 mb_eregi() 参数语义
如果没有匹配到内容,mb_ereg() 和 mb_eregi()
函数(regs
)的第三个参数现在将设置为空数组。以前,不会修改该参数。
放弃对 sslv2 stream 的支持
sslv2 stream 现已在 OpenSSL 中删除。
在编译时禁止 "return;" 用于类型化返回
在声明返回类型的函数中,没有参数的 return 语句现在触发 E_COMPILE_ERROR
(除非返回类型声明为
void),即使永远不会到达 return 语句。
用户贡献的备注 5 notes
For anyone migrating from 5.x to 7.1:
About "Array ordering when elements are automatically created during by reference assignments has changed" on this page
(http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.array-order)
The behaviour of 7.1 is THE SAME as of PHP 5. It is only 7.0 that differs.
See https://3v4l.org/frbUc
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
The backwards incompatible change 'The empty index operator is not supported for strings anymore' has a lot more implications than just a fatal error on the following code
<?php
$a = "";
$a[] = "hello world";
var_dump($a);
?>
This will give a fatal error in 7.1 but will work as expected in 7.0 or below and give you: (no notice, no warning)
array(1) {
[0]=>
string(11) "hello world"
}
However, the following is also changed:
<?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" }
?>
"OMFG! Why was session.hash_function removed?!? Dude!"
https://wiki.php.net/rfc/session-id-without-hashing
There. Saved ya a search.
ArgumentCountError - this modification is the main reason to avoid this version on older projects.
Regarding the ArgumentCountError, PHP 7.1+ does still support user functions with a variable number of arguments, using the "func(...$args) {}" syntax, see: https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
备份地址:http://www.lvesu.com/blog/php/migration71.incompatible.php