Skip to content

Latest commit

 

History

History
402 lines (357 loc) · 15.7 KB

Backward-incompatible-changes.md

File metadata and controls

402 lines (357 loc) · 15.7 KB

PHP5.6.x版本迁移至7.0.x版本

向后兼容说明

错误和异常处理的变更

许多的Fatal错误,包括一些可以被修正的Fatal错误,在PHP7中以Exceptions异常对待。这些Error Exceptions继承于 Error 类。而 Error 类则继承于异常基类 Throwable 接口。
PHP7中详细的Error相关的信息可以参考页面[ PHP7错误 ]。本文中仅仅介绍和向后兼容有关的信息如下。

内部构造函数在失败时抛出异常

在PHP7之前,类内部的构造函数在失败时总是返回NULL或者返回一个不可用的Object,但此版本开始,在构造函数初始化失败时总是会抛出异常

解析错误时会抛出 解析异常

Parser errors now throw a ParseError object. Error handling for eval() should now include a catch block that can handle this error. 解析错误,现在开始会抛出一个 解析异常 对象。eval() 函数现在开始可以通过 catch 捕捉异常,随之做相应处理。

E_STRICT 等级的报错被重新分配

所有E_STRICT级别的报错已重新分配到其他报错等级中。E_STRICT常量依然保留,所以当你设置报错等级为 **error_reporting(E_ALL|E_STRICT)**时,不会引起报错。
变更情况如下表 image

变量处理环节的变更

PHP7开始使用一种抽象的语法树来解析PHP代码文件。老版本的PHP因为PHP解析器的局限性是不可能实现这一特性的。但此处的改动引起了一些一致性问题,破坏了向后兼容性。本节详细介绍这块的情况。

对于间接变量、属性、方法的变动

间接的使用变量、属性、方法,现在开始严格按照从左到右的顺序执行,而不是以前混合各种形式产生各种可能。下表表明的这一改变引起的差异。 image 这块使用老得从右到左的方式的代码,必须重写了。通过花括号来明确顺序(见上图中间列),以使代码向前兼容PHP7.x,并向后兼容PHP5.x。

对于 list() 函数处理上的修改

list() 不再按照相反顺序插入元素

list()函数从此开始按照原数组中的顺序插入到函数参数制定的位置上,不再翻转数据。这点修改只会作用在list()函数参数一起用了数组的[]符号时。举例如下:

<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>

上述例子在PHP5中的输出为:

array(3) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>
  int(1)
}

而在PHP7中的输出为:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

在实际开发中,不建议使用依靠 list() 函数的参数来做排顺序这一操作,毕竟这样的hack用法在未来还是有可能调整。

list() 函数参数不再允许为空

list() 构造时不再允许参数为空的情况,下列情况将不再支持!

<?php
list() = $a;
list(,,) = $a;
list($x, list(), $y) = $a;
?>
list() 函数不再支持拆解字符串

list() 不再允许拆解字符串变量为字母,(str_split())[http://php.net/manual/en/function.str-split.php]函数可以用于做此事。

在数组中的元素通过引用方式创建时,数组顺序会被改变

数组中的元素在通过引用方式创建时,其数组顺序会被自动的改变。例如:

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

PHP5中的输出:

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

PHP7中的输出

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

Global 仅支持简单的变量

变量为值的变量的情况将不能再使用Global标记。如果真的需要,可以用花括号来间隔开写,例如下面代码:

<?php
function f() {
    // Valid in PHP 5 only.
    global $$foo->bar;

    // Valid in PHP 5 and 7.
    global ${$foo->bar};
}
?>

作为一个基本原则,这样的变量套变量的使用方式,在Global这种场景下是不被提倡的。

函数参数中的括号不再影响(行为?)

在PHP5中,参数若使被引用的并且使用括号,会没有报错发生。但在PHP7开始,这种场景都会印发一个报错。

<?php
function getArray() {
    return [1, 2, 3];
}

function squareArray(array &$a) {
    foreach ($a as &$v) {
        $v **= 2;
    }
}

// Generates a warning in PHP 7.
squareArray((getArray()));
?>

上述示例代码将会产生如下输出:

Notice: Only variables should be passed by reference in /tmp/test.php on line 13

foreach 的改变

关于 foreach 的修改比较少,主要是修改了数组遍历时的数组指针,以及修改了数组的迭代。

foreach 遍历期间不再修改数组指针

在PHP7之前,当数组通过foreach迭代时,数组指针会移动。现在开始,不再如此,见下面代码:

<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
    var_dump(current($array));
}
?>

PHP5中的输出

int(1)
int(2)
bool(false)

PHP7中的输出

int(0)
int(0)
int(0)

foreach 通过值遍历时,操作的值为数组的副本

当默认使用通过值遍历数组时,foreach实际操作的是数组的迭代副本,而非数组本身。这就意味着,foreach中的操作不会修改原数组的值。

foreach 通过引用遍历时,有更好的迭代特性

当使用引用遍历数组时,现在foreach在迭代中更好的跟踪变化。例如,在迭代中添加一个迭代值到数组中,例如下面代码:

<?php
$array = [0];
foreach ($array as &$val) {
    var_dump($val);
    $array[1] = 1;
}
?>

在PHP5的输出为:

int(0)

在PHP7的输出为:

int(0)
int(1)

non-Traversable 对象的遍历

non-Traversable 对象的遍历与通过引用遍历相似,具有相同的行为特性,在遍历期间对原数据进行的操作将会被感知

整形处理上的调整

无效的八进制常量

此前,八进制中包含无效数据会自动被截断(0128被当做为012)。现在,一个无效的八进制字面会造成分析错误。

负位置

位移的负数将抛出一个 ArithmeticError

<?php
var_dump(1 >> -1);
?>

PHP5中的输出:

int(0)

PHP7中的输出:

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2
Stack trace:
#0 {main}
  thrown in /tmp/test.php on line 2

超出范围的位移

位移(任一方向)超出一个整数的位宽度会得到0。以前,这种转变的行为是依赖于运行环境的机器架构结构。

字符串处理上的调整

十六进制字符串不再被认为是数字

含十六进制字符串不再被认为是数字。例如:

<?php
var_dump("0x123" == "291");
var_dump(is_numeric("0x123"));
var_dump("0xe" + "0x1");
var_dump(substr("foo", "0x1"));
?>

在PHP5中得输出:

bool(true)
bool(true)
int(15)
string(2) "oo"

在PHP7中得输出:

bool(false)
bool(false)
int(0)

Notice: A non well formed numeric value encountered in /tmp/test.php on line 5
string(3) "foo"

filter_var() 函数可以用于检查一个字符串中是否包含十六进制数,同时也可以转换一个字符串为十六进制数。

<?php
$str = "0xffff";
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int) {
    throw new Exception("Invalid integer!");
}
var_dump($int); // int(65535)
?>

\u{ 可能触发错误

由于新的Unicode转译语法,字符串中含有 **\u{ ** 时会触发Fatal错误。为了避免这一报错,应该避免反斜杠开头。

被移除的函数

这些函数被在PHP4.1.0开始被标记为过时的,在PHP7开始被删除。建议使用 call_user_func()call_user_func_array() 。你可以考虑下 变量函数或者其他的选择。

mcrypt 相关的

mcrypt_generic_end() 被删除,建议使用 mcrypt_generic_deinit() 。 此外,废弃的mcrypt_ecb(),mcrypt_cbc(),mcrypt_cfb()和mcrypt_ofb()功能,建议使用目前还支持的mcrypt_decrypt()与适当的MCRYPT_MODE_*常量。

intl 相关的

datefmt_set_timezone_id()与IntlDateFormatter::setTimeZoneID()别名被删除,建议使用datefmt_set_timezone()与IntlDateFormatter::setTimeZone()。

set_magic_quotes_runtime()与它的别名函数magic_quotes_runtime()都在PHP7中删除了。他们在PHP5.3.0中就被标记被过时的。

set_socket_blocking()已被移除,建议使用stream_set_blocking()。

dl() 在PHP-FPM中

dl()函数不能在PHP-FPM中使用了,它的功能做在了CLI、嵌入到SAPIs中了。

GD 类型的函数

PostScript Type1字体的支持已经从GD扩展删除,涉及的函数有:

  • imagepsbbox()
  • imagepsencodefont()
  • imagepsextendfont()
  • imagepsfreefont()
  • imagepsloadfont()
  • imagepsslantfont()
  • imagepstext() 建议使用TrueType字体和其相关的功能代替。

删除INI配置

删除的功能

下面的INI指令以及相关的功能被删除:

xsl.security_prefs

xsl.security_prefs指令已被删除。相反,该xsltprocessor::setsecurityprefs()方法用于控制在每个处理器上的安全选项。

其他不向后兼容的变更

New 对象不能被引用分配

New语句的结果不再能通过引用赋值给一个变量,如下代码:

<?php
class C {}
$c =& new C;
?>

PHP5中的输出:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3

PHP7中的输出:

Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3

无效的类、接口和特性的名字

下面的名称不能被用来类、接口、特性的名称:

  • bool
  • int
  • float
  • string
  • NULL
  • TRUE
  • FALSE 此外,下列名称不应该被使用。虽然他们不会产生在PHP 7中的一个错误,他们是保留供将来使用,应认为已过时。
  • resource
  • object
  • mixed
  • numeric

ASP语法标记、Script PHP语法标记被移除

使用ASP脚本标签,或者Script的PHP代码,已被删除。受影响的标签是: image

不允许调用不确定的情况

之前PHP5.6的过时说明中,静态调用一个非静态方法,会在静态调用中被提示未定义 $this ,并会报错。

<?php
class A {
    public function test() { var_dump($this); }
}

// Note: Does NOT extend A
class B {
    public function callNonStaticMethodOfA() { A::test(); }
}

(new B)->callNonStaticMethodOfA();
?>

在PHP5中会输出:

Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8
object(B)#1 (0) {
}

在PHP7中会输出:

Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8

Notice: Undefined variable: this in /tmp/test.php on line 3
NULL

yield 现在开始作为正确的(联想?)算子

yield 不再需要括号,可以作为一个正确的联想算子优先于 print 与 ** => **,这将产生下列行为:

<?php
echo yield -1;
// Was previously interpreted as
echo (yield) - 1;
// And is now interpreted as
echo yield (-1);

yield $foo or die;
// Was previously interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo) or die;
?>

括号可以用来消除歧义的情况。

函数不能有多个相同的名称的参数

不允许函数在参数中出现相同名称的参数。例如下列代码,将会产生 E_COMPILE_ERROR 的报错。

<?php
function foo($a, $b, $unused, $unused) {
    //
}
?>

$HTTP_RAW_POST_DATA 不再被支持。 可以使用 php://input 流数据来代替实现。

# 注释已被移除

INI文件中以#符号作为注释的内容已被移除,;符号将代替#,这个改变同样适用于PHP.ini文件,以及parse_ini_file()和parse_ini_string()处理文件期间。

用户贡献说明

暂无