php7类,PHP 7.1 新特性一览

PHP 7.1 release版本发布在即,本文整理一下 7.1 中的一些新特性以供了解。所有内容均选自官方 RFC 文档。

可空类型

可空类型主要用于参数类型声明和函数返回值声明。

主要的两种形式如下:

function answer(): ?int {

return null; //ok

}

function answer(): ?int {

return 42; // ok

}

function say(?string $msg) {

if ($msg) {

echo $msg;

}

}

从例子很容易理解,所指的就是通过 ? 的形式表明函数参数或者返回值的类型要么为指定类型,要么为 null。

此方法也可用于接口函数的定义:

interface Fooable {

function foo(?Fooable $f);

}

但有一个需要注意的地方:如果函数本身定义了参数类型并且没有默认值,即使是可空的,也不能省略,否则会触发错误。如下:

function foo_nullable(?Bar $bar) {}

foo_nullable(new Bar); // 可行

foo_nullable(null); // 可行

foo_nullable(); // 不可行

但是如果以上函数的参数定义为 ?Bar $bar = null 的形式,则第三种写法也是可行的。因为 = null 实际上相当于 ? 的超集,对于可空类型的参数,可以设定 null 为默认值。

list 的方括号简写

我们知道在 PHP5.4 之前只能通过 array() 来定义数组,5.4之后添加了 [] 的简化写法(省略了5个字符还是很实在的)。

// 5.4 之前

$array = array(1, 2, 3);

$array = array("a" => 1, "b" => 2, "c" => 3);

// 5.4 及之后

$array = [1, 2, 3];

$array = ["a" => 1, "b" => 2, "c" => 3];

引申到另外一个问题上,如果我们要把数组的值赋值给不同的变量,可以通过 list 来实现:

list($a, $b, $c) = $array;

是否也可以通过 [] 的简写来实现呢?

[$a, $b, $c] = $array;

以及下一个特性中会提到的 list 指定 key:

["a" => $a, "b" => $b, "c" => $c] = $array;

PHP7.1 实现了这个特性。但是要注意的是:出现在左值中的 [] 并不是数组的简写,是 list() 的简写。

但是并不仅仅如此,新的 list() 的实现并不仅仅可以出现在左值中,也能在 foreach 循环中使用:

foreach ($points as ["x" => $x, "y" => $y]) {

var_dump($x, $y);

}

不过因为实现的问题,list() 和 [] 不能相互嵌套使用:

// 不合法

list([$a, $b], [$c, $d]) = [[1, 2], [3, 4]];

// 不合法

[list($a, $b), list($c, $d)] = [[1, 2], [3, 4]];

// 合法

[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];

允许在 list 中指定 key

上文提到过,新的 list() 的实现中可以指定key:

$array = ["a" => 1, "b" => 2, "c" => 3];

["a" => $a, "b" => $b, "c" => $c] = $array;

这也就相当于:

$a = $array['a'];

$b = $array['b'];

$c = $array['c'];

和以往的区别在于以往的 list() 的实现相当于 key 只能是 0, 1, 2, 3 的数字形式并且不能调整顺序。执行以下语句:

list($a, $b) = [1 => '1', 2 => '2'];

会得到 PHP error: Undefined offset: 0... 的错误。

而新的实现则可以通过以下方式来调整赋值:

list(1 => $a, 2 => $b) = [1 => '1', 2 => '2'];

不同于数组的是,list 并不支持混合形式的 key,以下写法会触发解析错误:

// Parse error: syntax error, ...

list($unkeyed, "key" => $keyed) = $array;

更复杂的情况,list 也支持复合形式的解析:

$points = [

["x" => 1, "y" => 2],

["x" => 2, "y" => 1]

];

list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points;

$points = [

"first" => [1, 2],

"second" => [2, 1]

];

list("first" => list($x1, $y1), "second" => list($x2, $y2)) = $points;

以及循环中使用:

$points = [

["x" => 1, "y" => 2],

["x" => 2, "y" => 1]

];

foreach ($points as list("x" => $x, "y" => $y)) {

echo "Point at ($x, $y)", PHP_EOL;

}

void 返回类型

PHP7.0 添加了指定函数返回类型的特性,但是返回类型却不能指定为 void,7.1 的这个特性算是一个补充:

function should_return_nothing(): void {

return 1; // Fatal error: A void function must not return a value

}

以下两种情况都可以通过验证:

function lacks_return(): void {

// valid

}

function returns_nothing(): void {

return; // valid

}

定义返回类型为 void 的函数不能有返回值,即使返回 null 也不行:

function returns_one(): void {

return 1; // Fatal error: A void function must not return a value

}

function returns_null(): void {

return null; // Fatal error: A void function must not return a value

}

此外 void 也只适用于返回类型,并不能用于参数类型声明,或者会触发错误:

function foobar(void $foo) { // Fatal error: void cannot be used as a parameter type

}

类函数中对于返回类型的声明也不能被子类覆盖,否则会触发错误:

class Foo

{

public function bar(): void {

}

}

class Foobar extends Foo

{

public function bar(): array { // Fatal error: Declaration of Foobar::bar() must be compatible with Foo::bar(): void

}

}

类常量属性设定

这个特性说起来比较简单,就是现在类中的常量支持使用 public、private 和 protected 修饰了:

class Token {

// 常量默认为 public

const PUBLIC_CONST = 0;

// 可以自定义常量的可见范围

private const PRIVATE_CONST = 0;

protected const PROTECTED_CONST = 0;

public const PUBLIC_CONST_TWO = 0;

// 多个常量同时声明只能有一个属性

private const FOO = 1, BAR = 2;

}

此外,接口(interface)中的常量只能是 public 属性:

interface ICache {

public const PUBLIC = 0;

const IMPLICIT_PUBLIC = 1;

}

为了应对变化,反射类的实现也相应的丰富了一下,增加了 getReflectionConstant 和 getReflectionConstants 两个方法用于获取常量的额外属性:

class testClass {

const TEST_CONST = 'test';

}

$obj = new ReflectionClass( "testClass" );

$const = $obj->getReflectionConstant( "TEST_CONST" );

$consts = $obj->getReflectionConstants();

多条件 catch

在以往的 try ... catch 语句中,每个 catch 只能设定一个条件判断:

try {

// Some code...

} catch (ExceptionType1 $e) {

// 处理 ExceptionType1

} catch (ExceptionType2 $e) {

// 处理 ExceptionType2

} catch (\Exception $e) {

// ...

}

新的实现中可以在一个 catch 中设置多个条件,相当于或的形式判断:

try {

// Some code...

} catch (ExceptionType1 | ExceptionType2 $e) {

// 对于 ExceptionType1 和 ExceptionType2 的处理

} catch (\Exception $e) {

// ...

}

对于异常的处理简化了一些。

附:源 RFC 地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值