[翻译] PHP 7.2 中弃用的功能

PHP RFC: 7.2 弃用功能 已获批准。让我们来看一看,有哪些功能未来会抛出弃用提醒:

__autoload

__autoload 魔术方法,已经被 PHP 5.1 中的 spl_autoload_register 取代,并且在文档中不建议使用。spl_autoloadregister() 的一个主要优点,是能够提供多个组合的自动加载器,从而降低库的互操作性。这两种加载机制是互斥的,使用 \_autoload 的代码不能与使用 spl_autoloadregister 代码交互操作。由于后者更常用,并且也被 Composer 使用,所以 \_autoload() 机制现在仅具有非常有限的适用性。

$php_errormsg

当一个非致命错误被抛出时,如果在 ini 中设置了 track_errors (默认情况下已禁用),并且该错误未被错误处理器程序处理,则会在本地作用域中创建 $php_errormsg 变量。

整个行为非常神奇,除了 ini 相关的部分。error_get_last 函数提供了一种更干净的方式,来检索最后一个错误。PHP 7 还提供了 error_clear_last 函数,覆盖了 $php_errormsg 最后可能的用例,并且没有神奇的作用域操作。

create_function()

create_function() 是对 eval() 的简单包装。此函数可以创建一个函数,函数的参数列表和函数主体作为字符串参数传入。在 PHP 5.3 引入闭包之前,它提供了一种创建近似于 lambda 函数的方法。

由于其操作的性质,create_function() 除了是潜在的安全问题来源之外,还具有非常差的性能和内存使用特性。在各种情况下,使用真正的闭包是首选。

mbstring.func_overload

在 ini 中设置 mbstring.func_overload 将允许用 mbstring 扩展中的相似功能替换掉字符串函数的子集。例如,strlen() 将不再返回以字节为单位的字符串长度,而是根据当前选择的内部编码返回代码点中的长度。

这意味着使用 mbstring.func_overload 的代码,与几乎所有在基本字符串操作正常工作的假设下编写的代码都不兼容。一些库完全禁止 func_overload (例如 Symfony),其它的则会出现一些不可察觉的行为变化。希望支持 func_overload 的代码需要有在普通字符串函数和具有8位编码的 mbstring 函数之间切换的条件(但是,通常只有加密库才会这么做)。

(unset)cast

(unset)cast 转换一个值为 null。

这表示 (unset)expr 只是一个总返回 null 并且没有其它副作用的表达式。除了无用以外,也容易让人懵逼。很多人合理的假设 (unset)$a 的行为类似于 unset($a) ,而实际上没那么回事。

parse_str() 不传入第二个参数

parse_str() 函数用于将查询字符串解析为第二个参数传入的数组,如果没有传入,则解析为本地符号表。

第二种行为是来自 register_globals 黑暗时代的残余。当处理用户提供的数据时,存在严重的安全隐患。

gmp_random()

gmp_random() 函数返回一个 0 到 2**($n*BITS_PER_LIMB)-1 之间的随机 GMP 数,其中 $n 是函数参数,BITS_PER_LIMB 是 GMP/MPIR 实现的平台特定参数,未向用户公开。因此,使用此功能需要猜测 limb 大小,并且有平台依赖性。

作为补救 PHP 5.6 引入了可以精确控制使用的随机数范围的 gmp_random_bits() 和 gmp_random_range() 函数。应始终优先使用这些函数,而不是 gmp_random()。

each()

each() 函数被用于遍历一个数组,类似于 foreach。每次调用时返回一个具有当前 key 和 value 的数组,并将内部数组指针移动到下一个位置。手册中介绍的典型用法如下:

reset($array);
while (list($key, $val) = each($array)) {
    echo "$key => $val\n";
}

each() 函数不如 foreach,并且比它慢十倍。

assert() 传入字符参数

assert() 函数具有两种操作模式:如果它传入的不是字符串,它会断言该值是否为真。如果传入一个字符串则先执行 eval(),然后检查 eval() 的结果是否为真。

在 PHP 7 之前,这种行为是阻止断言表达式求值的唯一方法。从 PHP 7 开始,可以在 ini 中设置 zend.assertions 的值,来避免对断言表达式求值。因此,不再需要支持隐式评估的字符串参数。

assert() 的这种行为使得很容易引入微妙的远程代码执行漏洞。

错误处理器的 $errcontext 参数

$errcontext 是使用 set_error_handler() 设置错误处理程序时的最后一个参数。此参数为包含错误生成处的所有局部变量的数组。

这个功能对于优化有影响,因为 $errcontext 可用于修改当前范围中的所有引用和变量。据我所知,这个功能几乎无用,这里的权衡是不值得的。如果人们希望在错误的时候检查变量状态,他们应该使用适当的调试器。

请注意,错误上下文仅包含错误发生处的局部变量。包含 $this 和函数参数的错误回溯,会通过 debug_backtrace() 保持可用。

更多更改和投票细节,请查看 RFC

本文章首发在 Laravel China 社区

Night gathers, and now my watch begins.