PHP新特性(php7.0-php7.2)

概述

PHP在7发布后,仍有大量的新特性被加入出来。我们再来了解一下。我们可以在PHP官方文档的附录查阅相关更详细
内容。如果你想动手运行及演练各版本的示例代码,可以使用这个网站, 它可以向你展示PHP各版本下的运行结果。

标量类型声明及返回值类型声明

在PHP7中,函数和方法上都可以使用标量类型来对参数及返回值进行类型声明了.如果传入的参数类型及返回值类型
与声明的类型不匹配,将会报错。这里的类型匹配分两种情况,就是说标量类型声明有两种模式: 强制(默认)和严格模式。
在强制模式下,如整数、浮点数、整数字符串都可与声明的整型(int)匹配。而通过定义在文件首行的declare(strict_types=1);声明方式
将模式转为严格模式后,情况就完全变了。

1
2
3
4
5
6
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1)); // int(9)

转化为严格模式:

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

declare(strict_types=1);
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1)); // Fatal error: Uncaught TypeError: Argument 2 passed to sumOfInts() must be of the type integer, string given

null合并运算符

我们经常在一条语句中同时使用三目运算符和isset()的情况:如先判断某变量有没有赋值,如果没有就使用默认值。PHP7中
专门为此需求添加了一个语法糖。我们暂且称为null合并运算符(??)

1
2
3
4
5
6
7
8
// 此两行代码完全等价
//第一行代码表示把双问号前面的变量代入到isset()函数,isset()函数返回值决定整个表达式的值是这个变量还是双问号后面的值。
//按isset()函数的特性, 即使双问号前面的变量为空字符串,也是返回true;除非这个值没定义或被赋值为null
echo $username = $_GET['user'] ?? 'nobody';
echo $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

//还可以使用这种链式判断的方式,会先判断$_GET['user'],如果没赋值就再判断$_POST['user'],如果还没赋值就使用后面的值。
echo $username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

太空船操作符(组合比较符)

太空船操作符用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1

1
2
3
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

该运算符在排序回调函数里使用得最多,一行代码即可搞定之前的2次if判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$a = array(3, 2, 5, 6, 1);
usort($a, function($a, $b){
return $a <=> $b;
});
print_r($a);

//输出排序后的结果
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
)

define()定义常量数组

现在 define()函数可以用来定义数组类型的常量了

1
2
3
4
5
6
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"

匿名类

现在支持通过new class来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
匿名类除了没有类名、只能使用一次外,和普通类没有任何区别。同样可以传递参数到匿名类的构造器,也可以继承其他类、实现接口、使用trait等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// PHP 7 之前的代码
class Logger
{
public function log($msg)
{
echo $msg;
}
}

$util->setLogger(new Logger());

// 使用了 PHP 7+ 后的代码
$util->setLogger(new class {
public function log($msg)
{
echo $msg;
}
});

匿名类的官方说明

use关键字组合导入

从同一命名空间导入的类、函数和常量现在可以通过单个use语句一次性导入了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;

use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;

use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;

// PHP 7+ code
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};

新增整除函数intdiv()

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

可为空(Nullable)类型

上面说到PHP7中在传入函数参数与返回的结果上可以指定类型,但是在实际开发中,经常遇到返回结果为空的情况,这就又与指定的返回类型不匹配了。在PHP7.1中
在指定类型上又添加了可空特性,就是说传入的参数或者函数返回的结果要么是给定的类型,要么是null。

1
2
3
4
5
6
7
8
function test(?string $name)
{
var_dump($name);
}

test('tpunt'); // string(5) "tpunt"
test(null); // NULL
test(); // Fatal error: Uncaught ArgumentCountError: Too few arguments to function test(), 0 passed

再看一个可空返回值的情况,因为返回值为可空,所以返回值可为string类型,也可为null.

1
2
3
4
5
6
7
8
9
10
11
declare(strict_types=1);
function role(string $name) :?string{

if(in_array($name, array('admin', 'manager'))){
return 'admin';
}
return null;
}

var_dump(role('admin')); // string(5) "admin"
var_dump(role('trainee')); // NULL

void函数

PHP7.1中背后引入的void函数与C语言中类似.返回值声明为void类型的方法要么省去return语句,要么使用一个空return语句。对于void函数来说,null也不是一个合法的返回值。
下面来自官网的例子就可很好说明void函数的用途。(使用传引用的方式后就不需要返回值)

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

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

$a = 1;
$b = 2;
var_dump(swap($a, $b)); // NULL 获取一个void方法的返回值会得到null,并且不会产生任何警告
var_dump($a); // int(2)
var_dump($b); // int(1)

Symmetric array destructuring

我们之前对二维数组循环时,拿到的都是那个完整的第二维数组,如果我们只是想处理第二维数组的某个KEY而不需要完整的第二维数组时,
这个语法就很有用了。我们可以拿到第二维数组的某个值给一个变量,之后在循环体中直接使用这个变量即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$data = [
1 => ['name' => 'Tom', 'age' => 15],
2 => ['name' => 'Fred', 'age' => 20],
];

// PHP7.1+
foreach($data as $id => ['age' => $age] ){
echo $id .':'. ($age+1) . PHP_EOL;
}

// PHP 7.1-
foreach($data as $id => $row ){
echo $id .':'. ($row['age']+1) . PHP_EOL;
}

除此以外,短数组语法[]还添加了一个本事,就是可以实现和list()函数一样的功能

1
2
3
4
5
6
7
8
9
10
$data = [
[1, 'Tom'],
[2, 'Fred'],
];

// list() style
list($id1, $name1) = $data[0]; // 变量$id1为1,变量$name1为Tom

// [] style
[$id1, $name1] = $data[0]; // 变量$id1为1,变量$name1为Tom

类常量可见性设置

在PHP7.1中可以对类常量进行可见性设置

1
2
3
4
5
6
7
class ConstDemo
{
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}

多异常捕获处理

一个catch语句块现在可以通过管道字符(|)来实现多个异常的捕获。这对于需要同时处理来自不同类的不同异常时很有用。

1
2
3
4
5
try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}

list()现在支持键名

我们知道以前的版本中不支持使用关联数组对list()函数的赋值(只支持索引从0开始的索引数组赋值),在PHP7.1版本中添加了对关联数组的支持

1
2
3
$info = ['a' => 'coffee', 'b' => 'brown', 'c' => 'caffeine'];
list('a' => $drink, 'b' => $color, 'c' => $power) = $info;
print_r($drink); // coffee

支持为负的字符串偏移量

1
var_dump("abcdef"[-2]); // e

允许重写抽象方法(Abstract method)

在PHP7.2中抽象方法也可以被子类重写

  • © 2015-2020 watson

请我喝杯咖啡吧~

支付宝
微信