這是咱們期待已久的 PHP 7 系列文章的第一篇。php
或許你已經知道了,我在 PHP 5.0.0 時間軸 提的 RFC (Request For Comments)經過了, PHP 7 成爲 PHP 下一個主要版本的名稱。html
不管你對此話題有任何感想,PHP 7 是一個大事件,並且它將在今年發佈! PHP 7.0 時間軸 的 RFC 幾乎全票經過(32 對 2 )後,全部功能如今已經確立了,咱們將在六月中旬看到首個候選版本( RC )發佈。mysql
但這對你意味着什麼呢?咱們看到 5.x 新版本發佈後,許多 Web 主機都不肯升級。一個重要的新版本發佈難道不會帶來巨大的向後兼容隔斷,使得升級更加緩慢麼?正則表達式
答案是:視狀況而定。請繼續往下讀。sql
在新版本中,許多語言邊界狀況已經獲得處理。此外,性能與不一致性修復也是該版重點關注的問題。數組
接下來是細節討論。服務器
##不兼容性修復php7
不幸的是,needle/haystack 問題還未獲得修復。然而,兩個重要的 RFC 已經得到經過,它們將帶來一些指望已久的內部與用戶層的一致性。數據結構
最大的(也是最難以察覺的)變化是新增的一種 抽象語法樹( AST )——代碼在編譯過程當中的中間表示。有了這種表示,咱們能夠清理一些邊緣狀況的不一致,併爲未來開發一些極好的工具作好準備,好比使用 AST 生成性能更好的 OpCode。閉包
其次,統一變量語法 的引入,可能會致使更多問題。這解決了表達式求值中的許多不兼容問題。例如,可使用 ($object->closureProperty)() 調用分配給屬性的閉包函數 ,以及執行鏈靜態調用,以下所示:
class foo { static $bar = 'baz'; } class baz { static $bat = 'Hello World'; } baz::$bat = function () { echo "Hello World"; }; $foo = 'foo'; ($foo::$bar::$bat)();
然而,一些語法也在改變。特別是使用 variable->variables/properties 的語法。
在 PHP 7 以前,$obj->$properties['name'] 將訪問名稱屬於 「$properties」 數組名稱鍵(name key)的屬性。使用通用變量語法(Universal Variable Syntax)後,它將訪問名稱屬於 「$properties」 的屬性的名稱鍵。
或者更簡潔地說,若是使用如下語法:
$obj->$properties['name']
在 PHP 5.6,它將被解析爲:
$obj->{$properties['name']}
而在 PHP 7 中則爲:
{$obj->$properties}['name']
variable->variables 一般使用在邊界狀況,根據個人經驗, variable->properties 則更加經常使用,且不易用。然而,使用花括號(如上例所示)後,就能夠輕易確保在 PHP 5.6 和 7 中達到相同效果。
##性能
升級到 PHP 7 的最大緣由是性能提高,此性能提高主要是因爲引入 phpng 的變化帶來的。實際上,性能提高可能帶來更高的採納率,尤爲是那些通常狀況下不肯意升級的小主機,爲了讓同一臺機器承載更多客戶,他們極有可能升級。
到目前爲止,根據不一樣的基準測試,PHP 7 的性能與 Facebooks HHVM 持平,後者的特色是藉助實時(Just In Time)編譯器將 PHP 代碼編譯至機器指令(只要能夠)。
PHP 7 不具有 JIT ,雖然相關討論沸沸揚揚。添加 JIT 以後能帶來多少性能提高還沒有可知,但如有人有興趣建立一個的話,確定很是有趣!
除了性能提高,還應該節省大量的內存,由於內部數據結構的優化一直是性能改進實現的主要途徑。
##向後不兼容的改變
雖然內部開發人員盡力不去打破向後兼容性( BC ),可是想要推動語言的進步,無法老是兼顧兼容性。
然而,像因爲統一變量語法(Uniform Variable Syntax)致使打破的向後兼容性,這些不兼容可能是輕微的,好比 在試圖調用一個非對象的方法時致使的可捕獲的致命錯誤:
set_error_handler(function($code, $message) { var_dump($code, $message); }); $var = null; $var->method(); echo $e->getMessage(); // Fatal Error: Call to a member function method() on null echo "Hello World"; // 依舊會運行
此外,ASP 與腳本標籤已被刪除,這意味着不能夠再使用 <% 和 <%=,或 <script language="php」>(以及各自的結束標籤:%>,和 </script>)。
其餘更大的改變,能夠在 移除的全部棄用函數 中看到。
最重要的不兼容性改變還包括,兼容 POSIX 的正則表達式擴展、EXT/ereg(在 5.3 版本被棄用)和舊的 EXT/mysql 擴展(在 5.5 版本被棄用)均被移除。
另外一個小的不兼容性改變是不容許在 switch 中有多個 default cases 。PHP 7 以前,如下是容許的:
switch ($expr) { default: echo "Hello World"; break; default: echo "Goodbye Moon!"; break; }
這將致使只有後者被執行。在 PHP 7 中,這將致使:
Fatal error: Switch statements may only contain one default clause - Switch 語法只容許包含一個默認子句
##新功能
在面對向後不兼容帶來的影響時,咱們很有微詞。性能上的提高又讓咱們歡欣鼓舞。可是,最讓咱們醉心的是新的特性!新特性纔是讓每次發佈充滿樂趣的關鍵—— PHP 7 可不缺少新特性。
##標量類型提示和返回類型
我會最早介紹 PHP 7 添加的最具爭議的變化:標量類型提示。這一特性的添加一開始並未經過投票。接着該做者撤回了該 RFC。以後,許多執行以後相互抵觸的 RFC 被提了出來,通過一番公開的討論,原先的這個 RFC 仍是經過了。
對於你,最終用戶,而言,這意味着你能夠對標量類型進行類型提示( type-hint )。具體地說,標量類型包括:int,float,string,和 bool 。默認狀況下,類型提示不是嚴格的,這意味着他們將迫使原始類型轉化爲類型提示指定的類型。這意味着,若是你將 int(1) 傳入須要 float 類型的函數,它會變爲 float(1)。將 float(1.5) 傳入須要 int 類型的函數,它會變爲 int(1)。
這裏的一個例子:
function sendHttpStatus(int $statusCode, string $message) { header('HTTP/1.0 ' .$statusCode. ' ' .$message); } sendHttpStatus(404, "File Not Found"); // 傳了整形和字符串 sendHttpStatus("403", "OK"); // 字符串 "403" 強轉爲 int(403)
此外,將聲明 declare(strict_types=1);
放在任意文檔的頂部,能夠啓用嚴格模式,文檔中的任何函數調用都必須聽從指定的類型。Strict 與否取決於函數調用的文件,而非函數定義的文件。
若是一個類型提示不匹配,一個可捕獲的致命錯誤會被拋出:
<?php declare(strict_types=1); // 必須放置在第一行 sendHttpStatus(404, "File Not Found"); // 傳了整型和字符串 sendHttpStatus("403", "OK"); // Catchable fatal error: 傳給 sendHttpStatus() 的第一個參數類型必須是整形,目前提供的是字符串
此外,PHP 7 還支持 返回類型提示,它支持全部相同的類型做參數。這遵循與 hack 相同的語法,在括號後面插入冒號,而後是類型:
function isValidStatusCode(int $statusCode): bool { return isset($this->statuses[$statusCode]); }
在這個例子中:bool 代表該函數將返回一個布爾值。
返回類型提示的嚴格模式聽從與類型提示相同的法則。
##綜合比較運算符
我我的最喜歡的 PHP 7 新增特性是 綜合比較運算符,<=>,也稱爲飛船操做符。此處我多是帶我的喜愛的,由於是我寫的最初補丁,也影響了命名(T_SPACESHIP)。但這還是對 PHP 語言的一個好補充,與大於和小於操做符造成互補。
實際上,該操做符的工做方式與 strcmp(),或 version_compare() 基本一致。若是左側操做數小於右側,則返回 -1 , 兩邊相等則返回 0 ,若是左側大於右側則返回 1 。主要的區別在於,它能夠用在任何兩個操做數間,不只是字符串,還能夠是整數,浮點數,數組等等。
該操做符最多見的用法是在排序回調中:
// Pre Spacefaring^W PHP 7 function order_func($a, $b) { return ($a < $b) ? -1 : (($a > $b) ? 1 : 0); } // Post PHP 7 function order_func($a, $b) { return $a <=> $b; }
OneAPM for PHP 可以深刻到全部 PHP 應用內部完成應用性能管理 可以深刻到全部 PHP 應用內部完成應用性能管理和監控,包括代碼級別性能問題的可見性、性能瓶頸的快速識別與追溯、真實用戶體驗監控、服務器監控和端到端的應用性能管理。
##下一步
在本文中,咱們瞭解了 PHP 7 中最重要的不兼容性修復,已經兩大新特性。
在接下來的第二篇文章中,咱們將介紹 PHP 7 中重要的其餘六個功能。另外,咱們將在文章系列的最後介紹一些幫助 PHP 7 發展的方法。