php5.2.x php5.3.x php5.4.x php5.5.x php5.6.x 對比詳解
截至目前(2014.2), PHP 的最新穩定版本是 PHP5.5, 但有差不多一半的使用者仍在使用已經不在維護 [注] 的 PHP5.2, 其餘的一半使用者在使用 PHP5.3 [注].
因為 PHP 那“集百家之長”的蛋疼文法,加上社群氛圍不好,很多人對新版本,新特征并無興趣。
本文将會介紹自 PHP5.2 起,直至 PHP5.6 中增加的新特征。
PHP5.2 以前:autoload, PDO 和 MySQLi, 類型限制
PHP5.2:JSON 支援
PHP5.3:棄用的功能,匿名函數,新增魔術方法,命名空間,後期靜态綁定,Heredoc 和 Nowdoc, const, 三元運算符,Phar
PHP5.4:Short Open Tag, 數組簡寫形式,Traits, 内置 Web 伺服器,細節修改
PHP5.5:yield, list() 用于 foreach, 細節修改
PHP5.6: 常量增強,可變函數參數,命名空間增強
(2006前)
順便介紹一下 PHP5.2 已經出現但值得介紹的特征。
大家可能都知道 __autoload() 函數,如果定義了該函數,那麼當在代碼中使用一個未定義的類的時候,該函數就會被調用,你可以在該函數中加載相應的類實作檔案,如:
但該函數已經不被建議使用,原因是一個項目中僅能有一個這樣的 __autoload() 函數,因為 PHP 不允許函數重名。但當你使用一些類庫的時候,難免會出現多個 autoload 函數的需要,于是 spl_autoload_register() 取而代之:
spl_autoload_register() 會将一個函數注冊到 autoload 函數清單中,當出現未定義的類的時候,SPL [注] 會按照注冊的倒序逐個調用被注冊的 autoload 函數,這意味着你可以使用 spl_autoload_register() 注冊多個 autoload 函數.
注:SPL: Standard PHP Library, 标準 PHP 庫, 被設計用來解決一些經典問題(如資料結構).
即 PHP Data Object, PHP 資料對象,這是 PHP 的新式資料庫通路接口。
按照傳統的風格,通路 MySQL 資料庫應該是這樣子:
為了能夠讓代碼實作資料庫無關,即一段代碼同時适用于多種資料庫(例如以上代碼僅僅适用于MySQL),PHP 官方設計了 PDO.
除此之外,PDO 還提供了更多功能,比如:
面向對象風格的接口
SQL預編譯(prepare), 占位符文法
更高的執行效率,作為官方推薦,有特别的性能優化
支援大部分SQL資料庫,更換資料庫無需改動代碼
上面的代碼用 PDO 實作将會是這樣:
PDO 是官方推薦的,更為通用的資料庫通路方式,如果你沒有特殊需求,那麼你最好學習和使用 PDO.
但如果你需要使用 MySQL 所特有的進階功能,那麼你可能需要嘗試一下 MySQLi, 因為 PDO 為了能夠同時在多種資料庫上使用,不會包含那些 MySQL 獨有的功能。
MySQLi 是 MySQL 的增強接口,同時提供面向過程和面向對象接口,也是目前推薦的 MySQL 驅動,舊的C風格 MySQL 接口将會在今後被預設關閉。
MySQLi 的用法和以上兩段代碼相比,沒有太多新概念,在此不再給出示例,可以參見 PHP 官網文檔 [注]。
通過類型限制可以限制參數的類型,不過這一機制并不完善,目前僅适用于類和 callable(可執行類型) 以及 array(數組), 不适用于 string 和 int.
(2006-2011)
包括 json_encode(), json_decode() 等函數,JSON 算是在 Web 領域非常常用的資料交換格式,可以被 JS 直接支援,JSON 實際上是 JS 文法的一部分。
JSON 系列函數,可以将 PHP 中的數組結構與 JSON 字元串進行轉換:
輸出:
值得注意的是 json_decode() 預設會傳回一個對象而非數組,如果需要傳回數組需要将第二個參數設定為 true.
(2009-2012)
PHP5.3 算是一個非常大的更新,新增了大量新特征,同時也做了一些不向下相容的修改。
以下幾個功能被棄用,若在配置檔案中啟用,則 PHP 會在運作時發出警告。
這是 php.ini 中的一個選項(register_globals), 開啟後會将所有表單變量($_GET和$_POST)注冊為全局變量.
看下面的例子:
這段代碼在通過驗證時,将 $authorized 設定為 true. 然後根據 $authorized 的值來決定是否顯示頁面.
但由于并沒有事先把 $authorized 初始化為 false, 當 register_globals 打開時,可能通路 /auth.php?authorized=1 來定義該變量值,繞過身份驗證。
該特征屬于曆史遺留問題,在 PHP4.2 中被預設關閉,在 PHP5.4 中被移除。
對應 php.ini 中的選項 magic_quotes_gpc, 這個特征同樣屬于曆史遺留問題,已經在 PHP5.4 中移除。
該特征會将所有使用者輸入進行轉義,這看上去不錯,在第一章我們提到過要對使用者輸入進行轉義。
但是 PHP 并不知道哪些輸入會進入 SQL , 哪些輸入會進入 Shell, 哪些輸入會被顯示為 HTML, 是以很多時候這種轉義會引起混亂。
很多虛拟主機提供商使用 Safe Mode 來隔離多個使用者,但 Safe Mode 存在諸多問題,例如某些擴充并不按照 Safe Mode 來進行權限控制。
PHP官方推薦使用作業系統的機制來進行權限隔離,讓Web伺服器以不同的使用者權限來運作PHP解釋器,請參見第一章中的<code>最小權限原則</code>.
也叫閉包(Closures), 經常被用來臨時性地建立一個無名函數,用于回調函數等用途。
以上代碼定義了一個匿名函數,并指派給了 $func.
可以看到定義匿名函數依舊使用 function 關鍵字,隻不過省略了函數名,直接是參數清單。
然後我們又調用了 $func 所儲存的匿名函數。
匿名函數還可以用 use 關鍵字來捕捉外部變量:
上面的代碼定義了一個 arrayPlus() 函數(這不是匿名函數), 它會将一個數組($array)中的每一項,加上一個指定的數字($num).
在 arrayPlus() 的實作中,我們使用了 array_walk() 函數,它會為一個數組的每一項執行一個回調函數,即我們定義的匿名函數。
在匿名函數的參數清單後,我們用 use 關鍵字将匿名函數外的 $num 捕捉到了函數内,以便知道到底應該加上多少。
PHP 的面向對象體系中,提供了若幹“魔術方法”,用于實作類似其他語言中的“重載”,如在通路不存在的屬性、方法時觸發某個魔術方法。
随着匿名函數的加入,PHP 引入了一個新的魔術方法 __invoke().
該魔術方法會在将一個對象作為函數調用時被調用:
輸出毫無疑問是:
__callStatic() 則會在調用一個不存在的靜态方法時被調用。
PHP的命名空間有着前無古人後無來者的無比蛋疼的文法:
更多有關命名空間的文法介紹請參見官網 [注].
命名空間時常和 autoload 一同使用,用于自動加載類實作檔案:
當你執行個體化一個類 \XXOO\Test\A 的時候,這個類的完整限定名會被傳遞給 autoload 函數,autoload 函數将類名中的命名空間分隔符(反斜杠)替換為斜杠,并包含對應檔案。
這樣可以實作類定義檔案分級儲存,按需自動加載。
PHP 的 OPP 機制,具有繼承和類似虛函數的功能,例如如下的代碼:
輸出是:
可以看到,當在 A 中使用 <code>$this->funcXXOO()</code> 時,展現了“虛函數”的機制,實際調用的是 <code>B::funcXXOO()</code>.
然而如果将所有函數都改為靜态函數:
情況就沒這麼樂觀了,輸出是:
這是因為 self 的語義本來就是“目前類”,是以 PHP5.3 給 static 關鍵字賦予了一個新功能:後期靜态綁定:
這樣就會像預期一樣輸出了:
PHP5.3 對 Heredoc 以及 Nowdoc 進行了一些改進,它們都用于在 PHP 代碼中嵌入大段字元串。
Heredoc 的行為類似于一個雙引号字元串:
Heredoc 以三個左尖括号開始,後面跟一個辨別符(TEXT), 直到一個同樣的頂格的辨別符(不能縮進)結束。
就像雙引号字元串一樣,其中可以嵌入變量。
Heredoc 還可以用于函數參數,以及類成員初始化:
Nowdoc 的行為像一個單引号字元串,不能在其中嵌入變量,和 Heredoc 唯一的差別就是,三個左尖括号後的辨別符要以單引号括起來:
PHP5.3 起同時支援在全局命名空間和類中使用 const 定義常量。
舊式風格:
新式風格:
const 形式僅适用于常量,不适用于運作時才能求值的表達式:
可簡寫成:
即如果省略三元運算符的第二個部分,會預設用第一個部分代替。
Phar即PHP Archive, 起初隻是Pear中的一個庫而已,後來在PHP5.3被重新編寫成C擴充并内置到 PHP 中。
Phar用來将多個 .php 腳本打包(也可以打包其他檔案)成一個 .phar 的壓縮檔案(通常是ZIP格式)。
目的在于模仿 Java 的 .jar, 不對,目的是為了讓釋出PHP應用程式更加友善。同時還提供了數字簽名驗證等功能。
.phar 檔案可以像 .php 檔案一樣,被PHP引擎解釋執行,同時你還可以寫出這樣的代碼來包含(require) .phar 中的代碼:
更多資訊請參見官網 [注].
(2012-2013)
Short Open Tag 自 PHP5.4 起總是可用。
在這裡集中講一下有關 PHP 起止标簽的問題。即:
通常就是上面的形式,除此之外還有一種簡寫形式:
還可以把
簡寫成:
這種簡寫形式被稱為 Short Open Tag, 在 PHP5.3 起被預設開啟,在 PHP5.4 起總是可用。
使用這種簡寫形式在 HTML 中嵌入 PHP 變量将會非常友善。
對于純 PHP 檔案(如類實作檔案), PHP 官方建議頂格寫起始标記,同時 省略 結束标記。
這樣可以確定整個 PHP 檔案都是 PHP 代碼,沒有任何輸出,否則當你包含該檔案後,設定 Header 和 Cookie 時會遇到一些麻煩 [注].
注:Header 和 Cookie 必須在輸出任何内容之前被發送。
這是非常友善的一項特征!
所謂Traits就是“構件”,是用來替代繼承的一種機制。PHP中無法進行多重繼承,但一個類可以包含多個Traits.
Traits還有很多神奇的功能,比如包含多個Traits, 解決沖突,修改通路權限,為函數設定别名等等。
Traits中也同樣可以包含Traits. 篇幅有限不能逐個舉例,詳情參見官網 [注].
PHP從5.4開始内置一個輕量級的Web伺服器,不支援并發,定位是用于開發和調試環境。
在開發環境使用它的确非常友善。
其中localhost是監聽的ip,8000是監聽的端口,可以自行修改。
很多應用中,都會進行URL重寫,是以PHP提供了一個設定路由腳本的功能:
這樣一來,所有的請求都會由index.php來處理。
你還可以使用 XDebug 來進行斷點調試。
PHP5.4 新增了動态通路靜态方法的方式:
新增在執行個體化時通路類成員的特征:
新增支援對函數傳回數組的成員通路解析(這種寫法在之前版本是會報錯的):
(2013起)
yield關鍵字用于當函數需要傳回一個疊代器的時候, 逐個傳回值。
該函數的傳回值是一個數組:
可以用 list() 在 foreach 中解析嵌套的數組:
結果:
不推薦使用 mysql 函數,推薦使用 PDO 或 MySQLi, 參見前文。
不再支援Windows XP.
可用 <code>MyClass::class</code> 取到一個類的完整限定名(包括命名空間)。
empty() 支援表達式作為參數。
try-catch 結構新增 finally 塊。
定義常量時允許使用之前定義的常量進行計算:
允許常量作為函數參數預設值:
用于代替 <code>func_get_args()</code>
同時可以在調用函數時,把數組展開為函數參數:
命名空間支援常量和函數:
<a href="http://blog.segmentfault.com/jysperm/1190000000403307#%23">3 推薦</a>
【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)
【部落格】http://www.cnblogs.com/kenshinobiy/