PHP7各个版本新增特性

文章目录
  1. 1. 7.0.x
    1. 1.1. 新特性
      1. 1.1.1. null合并运算符
      2. 1.1.2. 太空船操作符
      3. 1.1.3. 新增整数除法函数intdiv()
      4. 1.1.4. 标量参数类型声明
      5. 1.1.5. 返回值类型声明
      6. 1.1.6. 通过define()定义常量数组
      7. 1.1.7. 匿名类
      8. 1.1.8. Closure::call()
    2. 1.2. 变更
      1. 1.2.1. 错误和异常处理
      2. 1.2.2. foreach变化
        1. 1.2.2.1. 循环时候不在改变内部数组指针
        2. 1.2.2.2. 通过引用遍历时候,能够动态更该遍历
      3. 1.2.3. 性能的提升与内存使用减少
  2. 2. 7.1.x
    1. 2.1. 新特性
      1. 2.1.1. 可为空(Nullable)类型
      2. 2.1.2. void类型返回值类型
      3. 2.1.3. iterable类型
      4. 2.1.4. 数组解构赋值
      5. 2.1.5. list()增强支持键名
      6. 2.1.6. 支持捕获多个类型
      7. 2.1.7. 支持负的字符串偏移量
      8. 2.1.8. is_iterable()验证变量是否是可迭代类型
  3. 3. 7.2.x
    1. 3.1. 对象类型
    2. 3.2. 参数类型拓展
  4. 4. 7.3.x
    1. 4.1. json_decode()抛出异常
    2. 4.2. is_countable()验证变量是否可以计数类型
    3. 4.3. array_key_first(), array_key_last()获取数组第一个和最后一个key
    4. 4.4. list支持引用赋值
  5. 5. 参考

PHP从5.6 跳过6直接来到7,带来新的语言特性,更带来性能很大飞越。根据w3techs统计截止截止2019年5月18月有79%网站使用PHP做为服务端开发语言,这些网站使用的PHP版本统计如下:

其中PHP 5 和 PHP 7细化分布下:

这里我们不探讨性能提升方面,只是看看PHP7带来了哪些语言上的新特性。下面是PHP7各个版本新增特性详细说明:

7.0.x

新特性

null合并运算符

PHP 5中我们常使用isset和三目运算符来判断变量是否存在,PHP 7开始可以使null合并运算符(??),如果变量存在且值不为NULL,则返回自身的值,否则返回它的第二个操作数。

1
2
3
4
5
6
7
8
9
<?php

$x = NULL;
$y = NULL;
$z = 3;
var_dump($x ?? $y ?? $z); // int(3)

$x = ["c" => "meaningful_value"];
var_dump($x["a"] ?? $x["b"] ?? $x["c"]); // string(16) "meaningful_value"

太空船操作符

太空船操作符(<=>),用于两个表达式,当aa小于、等于或者大于b时,分别返回-1、0、1

1
2
3
4
5
6
7
8
9
10
$array = [1, 2, 3, 4, 6];
// PHP 5
usort($array, function ($a, $b) {
return ($a < $b) ? -1 : ($a = $b ? 0 : 1);
});

// PHP 7
usort($array, function ($a, $b) {
return $a <=> $b;
});

新增整数除法函数intdiv()

intdiv用于整数的除法运算

1
2
3
<?php

var_dump(intdiv(10, 3)); // int(3)

标量参数类型声明

PHP 5也支持参数类型声明,但它只支持复合变量类型声明,比如类或数组声明。PHP 7 开始之后支持int,bool等标量类型声明了。具体支持支持类型如下:

类型 描述 最低 PHP版本
class/interface name 参数必须是类或者接口的一个实例 PHP 5.0.0
self 参数必须是当前类的实例 PHP 5.0.0
array 参数必须是一个数组 PHP 5.1.0
callable 参数必须是一个可回调类型 PHP 5.4.0
bool 参数必须布尔类型 PHP 7.0.0
float 参数必须是浮点类型 PHP 7.0.0
int 参数必须是整数类型 PHP 7.0.0
string 参数必须是字符串类型 PHP 7.0.0

返回值类型声明

返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同, 见上表

1
2
3
4
5
6
7
8
9
10
11
<?php

interface A {
static function make(): A;
}
class B implements A {
static function make(): A {
return new B();
}
}

通过define()定义常量数组

PHP 5.6中只能通过const定义数组常量,现在可以通过define()来定以

1
2
3
4
5
6
7
8
<?php
define('ANIMALS', [
'dog',
'cat',
'bird'
]);

echo ANIMALS[1]; // 输出 "cat"

匿名类

PHP 7 开始支持同 new class 来实例化一个匿名类,

1
2
3
4
5
6
7
8
9
10
<?php

$di = new DI();

$di->setLogger(new class {
public function log(string $msg) {
echo $msg;
}
}
})

Closure::call()

Closure::call() 用于绑定一个方法到对象上闭包并调用它,并有着更好的性能

1
2
3
<?php


变更

错误和异常处理

PHP 7 起大部分错误可以被作为Error异常抛出。PHP 5 使用错误报告等来处理错误, 可参看PHP错误与异常处理详解(一)

PHP 7 抛出的Error 可以通过catch(Error $e) {}来捕获或注册异常处理函数set_exception_handler来捕获。所有异常和错误类都实现了Throwalble接口。

Error的层次接口结构:

  • Throwable
    • Error
      • ArithmeticError
        • DivisionByZeroError
      • DivisionByZeroError
      • AssertionError
      • ParseError
      • TypeError
        • ArgumentCountError
    • Exception
      • ClosedGeneratorException
      • DOMException
      • ErrorException
      • IntlException
      • LogicException
        • BadFunctionCallException
          • BadMethodCallException
        • DomainException
        • InvalidArgumentException
        • LengthException
        • OutOfRangeException
      • PharException
      • ReflectionException
      • RuntimeException
        • OutOfBoundsException
        • OverflowException
        • PDOException
        • RangeException
        • UnderflowException
        • UnexpectedValueException

set_exception_handler()接收的对象不一定是Exception对象,有可能是Error对象

1
2
3
4
5
6
7
8
9
// PHP 5 时代代码
func handler(Excetion $e) { ... } // 如果此时接受到Error对象,将会导致fatal error
set_exception_handler('handler')

// 兼容PHP 5 和 7
function handler($e) {...}

// 仅支持 PHP 7
function handler(Throwalbe $e) { ... }

foreach变化

循环时候不在改变内部数组指针

PHP 7之前,当数组通过foreach 迭代时候,数组指针会移动。

1
2
3
4
5
6
<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
}

var_dump(current($array); // php 5 输出 bool(false); php 7 输出int(1)
通过引用遍历时候,能够动态更该遍历
1
2
3
4
5
6
<?php
$array = [0];
foreach ($array as &$val) { // 注意此处一定是引用遍历,否则没有效果
var_dump($val);
$array[1] = 1;
}

PHP 5 输出:

1
int(0)

PHP 7 输出:

1
2
int(0)
int(1)

注意PHP 5 和 PHP 7最后的数组$array都会多一个元素1

1
2
3
<?php

$array = [0, 1];

更多PHP 7.0.x 变更与新特性见从PHP 5.6.x 移植到 PHP 7.0.x

性能的提升与内存使用减少

PHP 7速度相比 5.6提升了2倍

php7_improved_performance

内存使用显著下降

php7_reduced_memory_usage

7.1.x

新特性

可为空(Nullable)类型

参数类型和返回值类型支持可为空类型。当在类型前面加一个问,传入的参数或函数返回值要么是该类型,要么是null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

function answer(): ?int {
return null; //ok
}

function answer(): ?int {
return 42; // ok
}

function answer(): ?int {
return new stdclass(); // error
}
function say(?string $msg) {
if ($msg) {
echo $msg;
}
}

say('hello'); // ok -- prints hello
say(null); // ok -- does not print
say(); // error -- missing parameter
say(new stdclass); //error -- bad type

void类型返回值类型

一个新的返回值类型void被引入。 返回值声明为 void 类型的方法要么干脆省去 return 语句,要么使用一个空的 return 语句。 对于 void 函数来说,NULL 不是一个合法的返回值,试图去获取void方法的返回值会得到NULL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
function swap(&$left, &$right) : void
{
if ($left === $right) {
return;
}

$tmp = $left;
$left = $right;
$right = $tmp;
}

$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);

上面程序会输出:

1
2
3
null
int(2)
int(1)

iterable类型

iterable类型可用于参数类型提示,或者返回值类型提示,表明参数或返回值是一个数组或者实现了Traversable接口的对象。

iterable类型可用于foreach循环。

1
2
3
4
5
6
<?php
function foo(iterable $iterable) {
foreach ($iterable as $value) {
// ...
}
}

数组解构赋值

结构赋值实现list()类似功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$array = [1, 2, 3];
[$a, $b, $c] = $array;
// 效果跟list($a, $b, $c) = $array; 一样

// 支持键名
$array = ['a' => 1, 'b' => 2, 'c' => 3];
["a" => $a, "b" => $b, "c" => $c] = $array;

$data = [
[1, 'Tom'],
[2, 'Fred'],
];
foreach ($data as list($id, $name)) {
}

foreach ($data as [$id, $name]) {
}

list()增强支持键名

1
2
3
<?php
$array = ['a' => 1, 'b' => 2, 'c' => 3];
list("a" => $a, "b" => $b, "c" => $c) = $array;

支持捕获多个类型

1
2
3
4
5
6
7
8
9
<?php

try {
// Some code...
} catch (ExceptionType1 | ExceptionType2 $e) {
// Code to handle the exception
} catch (\Exception $e) {
// ...
}

支持负的字符串偏移量

一个负数的偏移量表明从字符串结尾开始的偏移量

1
2
3
<?php
var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));

上面程序将会输出

1
2
string (1) "e"
int(3)

is_iterable()验证变量是否是可迭代类型

is_iterable用来验证变量是否是iterable伪类类型

1
2
3
4
5
6
<?php
var_dump(is_iterable([1, 2, 3])); // bool(true)
var_dump(is_iterable(new ArrayIterator([1, 2, 3]))); // bool(true)
var_dump(is_iterable((function () { yield 1; })())); // bool(true)
var_dump(is_iterable(1)); // bool(false)
var_dump(is_iterable(new stdClass())); // bool(false)

7.2.x

对象类型

对象类型用于输入参数和函数返回值都是任何对象乐西

1
2
3
4
5
6
7
8
<?php

function test(object $obj) : object
{
return new SplQueue();
}

test(new StdClass());

参数类型拓展

重写方法和接口实现的参数类型可以使任意类型,即使父类方法指定一个固定的参数类型

1
2
3
4
5
6
7
8
9
10
11
<?php

interface A
{
public function Test(array $input);
}

class B implements A
{
public function Test($input){} // type omitted for $input
}

更多新特性与变更见从PHP 7.1.x 移植到 PHP 7.2.x

7.3.x

json_decode()抛出异常

json_decode()第二个参数传入JSON_THROW_ON_ERROR,那么当json解析失败是,会抛出JsonException异常

7.2之前(含7.2)的获取json解析错误使用如下方法:

1
2
3
4
5
<?php

json_decode("{");
json_last_error() === JSON_ERROR_NONE // 结果是false
echo json_last_error_msg() // 输出 "Syntax error"

7.3起我们可以捕获json处理异常了:

1
2
3
4
5
6
7
8
9
10
11
<?php

use JsonException;

try {
$json = json_encode("{", JSON_THROW_ON_ERROR);
return base64_encode($json);
} catch (JsonException $e) {
echo $e->getMessage(); // 类似json_last_error_msg()
echo $e->getCode(); // 类似 json_last_error()
}

is_countable()验证变量是否可以计数类型

1
2
3
4
5
6
7
8
9
10
<?php

// 7.3之前
if (is_array($foo) || $foo instanceof Countable) {
// $foo is countable
}
// 7.3开始
if (is_countable($foo)) {
// $foo is countable
}

array_key_first(), array_key_last()获取数组第一个和最后一个key

1
2
3
4
<?php

$firstKey = array_key_first($array);
$lastKey = array_key_last($array);

list支持引用赋值

1
2
3
4
<?php

$array = [1, 2];
list($a, &$b) = $array;

等效于:

1
2
3
4
5
<?php

$array = [1, 2];
$a = $array[0];
$b =& $array[1];

参考