PHP 7.1 新特性一覽

PHP 7.1 release版本發佈在即,本文整理一下 7.1 中的一些新特性以供瞭解。全部內容均選自官方 RFC 文檔。php

可空類型

可空類型主要用於參數類型聲明和函數返回值聲明。數組

主要的兩種形式以下:函數

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

function say(?string $msg) {
    if ($msg) {
        echo $msg;
    }
}

從例子很容易理解,所指的就是經過 ? 的形式代表函數參數或者返回值的類型要麼爲指定類型,要麼爲 null.net

此方法也可用於接口函數的定義:code

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 爲默認值。ip

list 的方括號簡寫

咱們知道在 PHP5.4 以前只能經過 array() 來定義數組,5.4以後添加了 [] 的簡化寫法(省略了5個字符仍是很實在的)。ci

// 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;

是否也能夠經過 [] 的簡寫來實現呢?get

[$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
    }
}

類常量屬性設定

這個特性提及來比較簡單,就是如今類中的常量支持使用 publicprivateprotected 修飾了:

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;
}

爲了應對變化,反射類的實現也相應的豐富了一下,增長了 getReflectionConstantgetReflectionConstants 兩個方法用於獲取常量的額外屬性:

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 地址

相關文章
相關標籤/搜索