順風車運營研發團隊 王坤 發表至21CTO公衆號(https://mp.weixin.qq.com/s/ph...)php
PHP是一種跨平臺開源語言,也是迄今爲止最流行的Web開發語言,全球有超過80%的網站由 PHP 驅動。自1994年由Rasmus Lerdorf 建立以來已走過20多年,經歷了6個大版本的更迭。下面就來了解PHP7帶來的新特性。數組
2015年夏天,備受矚目的PHP7發佈了第一個Alpha版本。以後,通過大概3個 Beta 版本和8個RC 版本,2016年1月 PHP7正式發佈。PHP7是PHP一個很是重要的版本,相對於PHP5.x 版本,有着很是大的革新,尤爲是在性能方面。若是讀者的網站是使用的 PHP5.x,那麼使用PHP7後將幾乎無成本的獲得一倍的性能提高。感謝開發者!閉包
1. PHP7到底有多快!
下面咱們來測試下PHP7性能提高到底有多少。本地環境下以相同的編譯參數分別安裝PHP5.5.3八、PHP7的第一個正式版本7.0.2和7.1.0版本,在CLI 模式下運行PHP 源碼中的基準測試腳本。架構
(1)測試環境函數
本地搭建的vagrant虛擬機,操做系統CentOS7,單核CPU 2.00GHz,內存1GB。性能
(2)基準測試指標測試
q Time——執行時間,以秒爲單位;優化
q %rel, gain——相對於上一版本節省的執行時間;網站
q %abs, gain——與 PHP 5.5.38 相比腳本節省的執行時間。this
測試結果如表1-1所示。
表1-1 測試結果
由上邊的測試結果能夠看出來,PHP7.1.0 的基準性能幾乎是PHP5.5.38的3倍左右,開啓了 opcache 的狀況下更是達到了4.4倍之多,這是一個很是顯著的提高,這些性能提高是如何作到的呢,本書後續的章節將一一介紹。
注意:這裏的測試是純 CPU 的基準測試,5次運行取平均值,不包括其餘方面的測試,在實際的項目或者其餘運行環境下可能有所差別。
2. PHP7炫目新特性
PHP7 除了在性能方面的極大提高,還添加了不少新的特性,如太空船操做符、標量類型聲明、返回值的類型聲明、全局的 throwable 接口、抽象語法樹等,下邊咱們分別介紹。
(1)太空船操做符
太空船操做符用於比較兩個表達式。例如,當 $a 小於、等於或大於 $b 時它分別返回 -一、0 或 1。比較的原則沿用 PHP 的常規比較規則進行。
<?php // 整數 echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // 浮點數 echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // 字符串 echo "a" <=>"a"; // 0 echo "a" <=>"b"; // -1 echo "b" <=>"a"; // 1
(2)標量類型聲明和返回值的類型聲明
PHP7 能夠對下面幾種類型的參數作聲明:字符串(string)、整型 (int)、浮點型 (float) 以及布爾型 (bool)。注意參數類型聲明不受制於默認模式和嚴格模式,均可以聲明。默認模式下,當傳入的參數不符合聲明類型時,會首先嚐試轉換類型;而嚴格模式下,則直接報錯。
例以下面的代碼:
<?php declare(strict_types=1); // strict_types=1表示開啓嚴格模式 function sumOfInts(int ...$ints) { return array_sum($ints); } var_dump(sumOfInts(2, '3.1', 4.1)); // 運行結果: // Fatal error: Uncaught TypeError:Argument 2 passed to sumOfInts() must be of the type integer, string given…
當註釋掉第二行代碼,程序才能夠正常運行——PHP 會首先嚐試把 '3.1' 轉爲 int 型的 3,而後再執行(注:這裏的類型轉換僅受制於可轉換的類型,例如不能把 'a' 轉爲 int 型)。可是當開啓嚴格模式後,代碼會直接報錯。由於函數的參數被聲明爲 int 型,可是傳入的參數中包含一個string型和一個float型。
咱們修改上面代碼,再來看下返回值類型限制的狀況:
<?php declare(strict_types=1); function sumOfInts(int ...$ints) : int { return array_sum($ints); } var_dump(sumOfInts(2, 3, 4)); // 運行結果: // int(9)
這段代碼咱們額外聲明瞭返回值的類型爲int型。若是返回值的類型不是 int型,在默認模式下,PHP會首先嚐試轉換返回值的類型爲 int型,若是不能轉換則會直接報錯。
PHP7.1 對函數返回值的聲明作了擴充,能夠定義其返回值爲 void,不管是否開啓嚴格模式,只要函數中有 return; 之外的其餘 return 語句都會報錯。
注:參數類型不能夠是 void。
<?php declare(strict_types=1); function sumOfInts(int ...$ints) : void { // return array_sum($ints); // return null; return; } var_dump(sumOfInts(2, 3, 4)); // 運行結果: // NULL
PHP7.1.0 對參數類型和返回值類型還有進一步的支持,其類型能夠是可空類型,在參數或返回值類型聲明前邊加上 「?」, 表示返回值要麼是 null 要麼是聲明的類型:
<?php declare(strict_types=1); function test(?int $a): ?int { return $a; } var_dump(test(null)); // NULL var_dump(test(1)); // 1 var_dump(test('a')); // ERROR
(3)null合併操做符
在 PHP7 以前,咱們會常常寫這樣的代碼:
<?php $page = isset($_GET['page']) ?$_GET['page'] : 0;
PHP7 提供了一個新的語法糖 ??,若是變量存在且值不爲NULL,它會返回自身的值,不然返回它的第二個操做數。咱們能夠這樣改寫代碼:
<?php $page = $_GET['page'] ?? 0;
當代碼中有連續的三元運算符的時候還能夠像下邊這樣寫:
<?php $page = $_GET['page'] ?? $_POST['page']?? 0;
看起來是否是簡化了不少?
(4)常量數組
PHP7 以前是沒法經過 define 來定義一個數組常量的,PHP7 支持了這個操做:
<?php define('ANIMALS', [ 'dog', 'cat', 'bird' ]);
(5)namespace 批量導入
PHP7 以前若是要導入一個 namespace 下的多個 class ,咱們須要這樣寫:
<?php use Space\ClassA; use Space\ClassB; use Space\ClassC as C;
在 PHP7 中支持批量導入:
<?php use Space\{ClassA, ClassB, ClassC asC};
(6)throwable 接口
在 PHP7 以前,若是代碼中有語法錯誤,或者 fater error 時,程序會直接報錯退出,可是在 PHP7 中有了改變。PHP7 實現了全局 throwable 接口,原來的 Exception 和部分 Error 實現了該接口。這種 Error 能夠像 Exception 異常同樣被第一個匹配的 try / catch 塊捕獲。若是沒有匹配的 catch 塊,則調用異常處理函數進行處理。若是還沒有註冊異常處理函數,則按照傳統方式處理(Fatal Error)。
Error 類並不是繼承自 Exception 類,因此不能用 catch (Exception$e) { ... } 來捕獲 Error。能夠用 catch (Error $e) { ... },或者經過註冊異常處理函數(set_exception_handler())來捕獲 Error:
<?php try { undefindfunc(); } catch (Error $e) { var_dump($e); } // or set_exception_handler(function($e){ var_dump($e); }); undefindfunc();
(7)Closure::call()
在 PHP7 以前咱們須要動態給一個對象添加方法時能夠經過 Closure 來複制一個閉包對象綁定到一個 $this 對象和類做用域:
<?php class Test { private $num = 1; } $f = function() { return $this->num + 1; }; $test = $f->bindTo(new Test,'Test'); echo $test(); // 2
在 PHP7 中新添加了 Closure::call(),能夠經過 call 來暫時綁定一個閉包對象到 $this 對象並調用它:
<?php class Test { private $num = 1; } $f = function() { return $this->num + 1; }; echo $f->call(new Test); // 2
(8)intdiv 函數
PHP7 還增長了一個新的整除函數,代碼中不須要再手動轉一下了:
<?php // var_dump(intval(10 / 3)); var_dump(intdiv(10, 3));
(9)list 的方括號寫法
咱們知道能夠經過 list 來實現解構賦值,以下:
<?php $arr = [1, 2, 3]; list($a, $b, $c) = $arr;
PHP7.1.0 對其作了進一步的優化,能夠寫成以下方式:
<?php $arr = [1, 2, 3]; [$a, $b, $c] = $arr;
注意:這裏的 [] 並非數組的意思,只是 list 的簡略形式。
除了上文這些,PHP7 還有不少其餘的改變和特性。例如 foreach 遍歷數組再也不修改內部指針、移除了 ASP 和 script PHP 標籤、移除了$HTTP_RAW_POST_DATA、匿名類、類常量可見性等,讀者能夠自行嘗試。
本文節選自《PHP 7底層設計與源碼實現》
推薦理由: