在过去如果我们调用一个用户定义的函数时,提供的参数不足,那么将会产生警告(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
禁止动态调用($func()
或 array_map('extract', ...)
的形式等)某些函数。这些函数会检查或修改另一个作用域,并呈现出不明确且不可靠的行为。函数如下:
<?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_PHP
作为 mt_srand() 的可选第二个参数,以保留旧的(不正确的)实现。
rand() 和 srand() 现已成为 mt_rand() 和 mt_srand() 的别名。这意味着以下函数已经更改:rand()、shuffle()、str_shuffle() 和 array_rand()。
ASCII 删除控制字符(0x7F
)不能用于未加引号的标识符中。
error_log
更改为 syslog
值
如果 error_log
ini 设置为 syslog
,PHP 错误等级会映射到 syslog
错误级别。这在错误日志中带来了更好的区分,与之前相反,之前所有的错误只记录了错误级别。
对于在执行构造方法时抛出异常的对象,现在析构方法绝不会被调用。在先前的版本中,这个行为取决于对象是否在构造方法以外的地方呗引用(例如一个错误堆栈回溯)
call_user_func() 现在在调用一个以引用作为参数的函数时将始终产生一个警告。先前这取决于这个调用行为是否完全符合条件。
此外,call_user_func() 和 call_user_func_array() 在这种情况下将不再中断函数调用。现在会出现包含“expected reference”的警告信息,但函数调用将正常进行。
对字符串使用一个空索引操作符(例如$str[] = $x
)将会抛出一个致命错误,而不是静默地将其转为一个数组。
下列 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 错误的错误消息已从“可捕获的致命错误”更改为“可恢复的致命错误”。
unserialize() 的 $options 参数的 allowed_classes
元素现在是严格类型,也就是说,如果指定了 array 或 bool 以外的任何内容,则
unserialize() 返回 false
并发出 E_WARNING
。
DateTime 和 DateTimeImmutable
现在构造当前时间时正确地包含微秒,无论是明确指定的还是使用相对字符串(例如 "first day of next
month"
)。这意味着两个新创建的实例的原生比较现在更有可能返回 false
而不是 true
:
<?php
new DateTime() == new DateTime();
?>
在 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) {};
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()
函数(regs
)的第三个参数现在将设置为空数组。以前,不会修改该参数。
sslv2 stream 现已在 OpenSSL 中删除。
在声明返回类型的函数中,没有参数的 return 语句现在触发 E_COMPILE_ERROR
(除非返回类型声明为
void),即使永远不会到达 return 语句。