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
。
此方法也可用於接口函數的定義:
<?php
interface Fooable {
function foo(?Fooable $f);
}
但有一個需要注意的地方:如果函數本身定義了參數類型並且沒有默認值,即使是可空的,也不能省略,否則會觸發錯誤。如下:
<?php
function foo_nullable(?Bar $bar) {}
foo_nullable(new Bar); // 可行
foo_nullable(null); // 可行
foo_nullable(); // 不可行
但是如果以上函數的參數定義為 ?Bar $bar = null
的形式,則第三種寫法也是可行的。因為 = null
實際上相當於 ?
的超集,對於可空類型的參數,可以設定 null
為默認值。
我們知道在 PHP5.4 之前只能通過 array()
來定義數組,5.4之後添加了 []
的簡化寫法(省略了5個字符還是很實在的)。
<?php
// 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
來實現:
<?php
list($a, $b, $c) = $array;
是否也可以通過 []
的簡寫來實現呢?
<?php
[$a, $b, $c] = $array;
以及下一個特性中會提到的 list 指定 key:
<?php
["a" => $a, "b" => $b, "c" => $c] = $array;
PHP7.1 實現了這個特性。但是要注意的是:出現在左值中的 []
並不是數組的簡寫,是 list()
的簡寫。
但是並不僅僅如此,新的 list()
的實現並不僅僅可以出現在左值中,也能在 foreach
循環中使用:
<?php
foreach ($points as ["x" => $x, "y" => $y]) {
var_dump($x, $y);
}
不過因為實現的問題,list()
和 []
不能相互嵌套使用:
<?php
// 不合法
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:
<?php
$array = ["a" => 1, "b" => 2, "c" => 3];
["a" => $a, "b" => $b, "c" => $c] = $array;
這也就相當於:
<?php
$a = $array['a'];
$b = $array['b'];
$c = $array['c'];
和以往的區別在於以往的 list()
的實現相當於 key 只能是 0, 1, 2, 3
的數字形式並且不能調整順序。執行以下語句:
<?php
list($a, $b) = [1 => '1', 2 => '2'];
會得到 PHP error: Undefined offset: 0...
的錯誤。
而新的實現則可以通過以下方式來調整賦值:
<?php
list(1 => $a, 2 => $b) = [1 => '1', 2 => '2'];
不同於數組的是,list
並不支持混合形式的 key,以下寫法會觸發解析錯誤:
<?php
// Parse error: syntax error, ...
list($unkeyed, "key" => $keyed) = $array;
更復雜的情況,list
也支持復合形式的解析:
<?php
$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;
以及循環中使用:
<?php
$points = [
["x" => 1, "y" => 2],
["x" => 2, "y" => 1]
];
foreach ($points as list("x" => $x, "y" => $y)) {
echo "Point at ($x, $y)", PHP_EOL;
}
PHP7.0 添加了指定函數返回類型的特性,但是返回類型卻不能指定為 void
,7.1 的這個特性算是一個補充:
<?php
function should_return_nothing(): void {
return 1; // Fatal error: A void function must not return a value
}
以下兩種情況都可以通過驗證:
<?php
function lacks_return(): void {
// valid
}
function returns_nothing(): void {
return; // valid
}
定義返回類型為 void
的函數不能有返回值,即使返回 null
也不行:
<?php
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
也只適用於返回類型,並不能用於參數類型聲明,或者會觸發錯誤:
<?php
function foobar(void $foo) { // Fatal error: void cannot be used as a parameter type
}
類函數中對於返回類型的聲明也不能被子類覆蓋,否則會觸發錯誤:
<?php
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
修飾了:
<?php
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
屬性:
<?php
interface ICache {
public const PUBLIC = 0;
const IMPLICIT_PUBLIC = 1;
}
為了應對變化,反射類的實現也相應的豐富了一下,增加了 getReflectionConstant
和 getReflectionConstants
兩個方法用於獲取常量的額外屬性:
<?php
class testClass {
const TEST_CONST = 'test';
}
$obj = new ReflectionClass( "testClass" );
$const = $obj->getReflectionConstant( "TEST_CONST" );
$consts = $obj->getReflectionConstants();
在以往的 try ... catch
語句中,每個 catch
只能設定一個條件判斷:
<?php
try {
// Some code...
} catch (ExceptionType1 $e) {
// 處理 ExceptionType1
} catch (ExceptionType2 $e) {
// 處理 ExceptionType2
} catch (\Exception $e) {
// ...
}
新的實現中可以在一個 catch
中設置多個條件,相當於或的形式判斷:
<?php
try {
// Some code...
} catch (ExceptionType1 | ExceptionType2 $e) {
// 對於 ExceptionType1 和 ExceptionType2 的處理
} catch (\Exception $e) {
// ...
}
對於異常的處理簡化了一些。
PHP 7革新與性能優化 http://www.linuxidc.com/Linux/2015-09/123136.htm
PHP 7 ,你值得擁有 http://www.linuxidc.com/Linux/2015-06/118847.htm
在 CentOS 7.x / Fedora 21 上面體驗 PHP 7.0 http://www.linuxidc.com/Linux/2015-05/117960.htm
CentOS 6.3 安裝LNMP (PHP 5.4,MyySQL5.6) http://www.linuxidc.com/Linux/2013-04/82069.htm
在部署LNMP的時候遇到Nginx啟動失敗的2個問題 http://www.linuxidc.com/Linux/2013-03/81120.htm
Ubuntu安裝Nginx php5-fpm MySQL(LNMP環境搭建) http://www.linuxidc.com/Linux/2012-10/72458.htm
《細說PHP》高清掃描PDF+光盤源碼+全套教學視頻 http://www.linuxidc.com/Linux/2014-03/97536.htm
CentOS 6中配置PHP的LNMP的開發環境 http://www.linuxidc.com/Linux/2013-12/93869.htm
PHP 的詳細介紹:請點這裡
PHP 的下載地址:請點這裡