1. 運算符(NULL 合並運算符)
把這個放在第一個說是因為我覺得它很有用。用法:
$a = $_GET['a'] ?? 1;
它相當於:
$a = isset($_GET['a']) ? $_GET['a'] : 1;
我們知道三元運算符是可以這樣用的:
$a ?: 1
但是這是建立在 $a 已經定義了的前提上。新增的 ?? 運算符可以簡化判斷。
2. 函數返回值類型聲明
官方文檔提供的例子(注意 … 的邊長參數語法在 PHP 5.6 以上的版本中才有):
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
以上例程會輸出:
Array
(
[0] => 6
[1] => 15
[2] => 24
)
從這個例子中可以看出現在函數(包括匿名函數)都可以指定返回值的類型。
這種聲明的寫法有些類似於 swift:
func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
這個特性可以幫助我們避免一些 PHP 的隱式類型轉換帶來的問題。在定義一個函數之前就想好預期的結果可以避免一些不必要的錯誤。
不過這里也有一個特點需要注意。PHP 7 增加了一個 declare 指令:strict_types,既使用嚴格模式。
使用返回值類型聲明時,如果沒有聲明為嚴格模式,如果返回值不是預期的類型,PHP 還是會對其進行強制類型轉換。但是如果是嚴格模式, 則會出發一個 TypeError 的 Fatal error。
強制模式:
function foo($a) : int
{
return $a;
}
foo(1.0);
以上代碼可以正常執行,foo 函數返回 int 1,沒有任何錯誤。
嚴格模式:
declare(strict_types=1);
function foo($a) : int
{
return $a;
}
foo(1.0);
# PHP Fatal error: Uncaught TypeError: Return value of foo() must be of the type integer, float returned in test.php:6
在聲明之后,就會觸發致命錯誤。
是不是有點類似與 js 的 strict mode?
3. 標量類型聲明
PHP 7 中的函數的形參類型聲明可以是標量了。在 PHP 5 中只能是類名、接口、array 或者 callable (PHP 5.4,即可以是函數,包括匿名函數),現在也可以使用 string、int、float和 bool 了。
官方示例:
// Coercive mode
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
var_dump(sumOfInts(2, '3', 4.1));
以上例程會輸出:
int(9)
需要注意的是上文提到的嚴格模式的問題在這里同樣適用:強制模式(默認,既強制類型轉換)下還是會對不符合預期的參數進行強制類型轉換,嚴格模式下則觸發 TypeError 的致命錯誤。
4. use 批量聲明
PHP 7 中 use 可以在一句話中聲明多個類或函數或 const 了:
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};
但還是要寫出每個類或函數或 const 的名稱(並沒有像 python 一樣的 from some import * 的方法)。
需要留意的問題是:如果你使用的是基於 composer 和 PSR-4 的框架,這種寫法是否能成功的加載類文件?其實是可以的,composer 注冊的自動加載方法是在類被調用的時候根據類的命名空間去查找位置,這種寫法對其沒有影響。
5. 太空艙操作符(組合比較操作符)
太空船操作符用於比較兩個表達式。當$a小於、等於或大於$b時它分別返回-1、0或1。 比較的原則是沿用 PHP 的常規比較規則進行的。
// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
6. 通過 define() 定義常量數組
Array 類型的常量現在可以通過 define() 來定義。在 PHP5.6 中僅能通過 const 定義。
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
?>
7. 迭代器
通過添加 yield 關鍵字支持了 generators,Generators 提供了一個更簡單的方法實現迭代器,不需要實現 Iterator 接口
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
以上例程會輸出:
1 2 3
8. 匿名類
現在支持通過new class 來實例化一個匿名類,這可以用來替代一些“用后即焚”的完整類定義。
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
以上例程會輸出:
object(class@anonymous)#2 (0) {
}
詳細文檔可以參考 匿名類.
9. 閉包 Closure::call()
Closure::call() 現在有着更好的性能,簡短干練的暫時綁定一個方法到對象上閉包並調用它。
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);
以上例程會輸出:
1 1
10. 其他的特性
其他的一些特性我就不一一介紹了,有興趣可以查看官方文檔:
