因為 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: 常量增強,可變函數參數,命名空間增強 一、PHP5.2以前(2006前) 順便介紹一下 PHP5.2 已經出現但值得介紹的特征。 autoload 大家可能都知道 __autoload() 函數,如果定義了該函數,那麼當在代碼中使用一個未定義的類的時候,該函數就會被調用,你可以在該函數中加載相應的類實現文件,如: 代碼如下:function __autoload($classname) { require_once("{$classname}.php") } 但該函數已經不被建議使用,原因是一個項目中僅能有一個這樣的 __autoload() 函數,因為 PHP 不允許函數重名。但當你使用一些類庫的時候,難免會出現多個 autoload 函數的需要,於是 spl_autoload_register() 取而代之: 復制代碼 代碼如下:spl_autoload_register(function($classname) { require_once("{$classname}.php") }); spl_autoload_register() 會將一個函數注冊到 autoload 函數列表中,當出現未定義的類的時候,SPL [注] 會按照注冊的倒序逐個調用被注冊的 autoload 函數,這意味著你可以使用 spl_autoload_register() 注冊多個 autoload 函數. 注:SPL: Standard PHP Library, 標准 PHP 庫, 被設計用來解決一些經典問題(如數據結構). PDO 和 MySQLi 即 PHP Data Object, PHP 數據對象,這是 PHP 的新式數據庫訪問接口。 按照傳統的風格,訪問 MySQL 數據庫應該是這樣子: 代碼如下:// 連接到服務器,選擇數據庫 $conn = mysql_connect("localhost", "user", "password"); mysql_select_db("database"); // 執行 SQL 查詢 $type = $_POST['type']; $sql = "SELECT * FROM `table` WHERE `type` = {$type}"; $result = mysql_query($sql); // 打印結果 while($row = mysql_fetch_array($result, MYSQL_ASSOC)) { foreach($row as $k => $v) print "{$k}: {$v}n"; } // 釋放結果集,關閉連接 mysql_free_result($result); mysql_close($conn); 為了能夠讓代碼實現數據庫無關,即一段代碼同時適用於多種數據庫(例如以上代碼僅僅適用於MySQL),PHP 官方設計了 PDO. 除此之外,PDO 還提供了更多功能,比如: 1.面向對象風格的接口 2.SQL預編譯(prepare), 占位符語法 3.更高的執行效率,作為官方推薦,有特別的性能優化 4.支持大部分SQL數據庫,更換數據庫無需改動代碼 上面的代碼用 PDO 實現將會是這樣: 代碼如下:// 連接到數據庫 $conn = new PDO("mysql:host=localhost;dbname=database", "user", "password"); // 預編譯SQL, 綁定參數 $query = $conn->prepare("SELECT * FROM `table` WHERE `type` = :type"); $query->bindParam("type", $_POST['type']); // 執行查詢並打印結果 foreach($query->execute() as $row) { foreach($row as $k => $v) print "{$k}: {$v}n"; } PDO 是官方推薦的,更為通用的數據庫訪問方式,如果你沒有特殊需求,那麼你最好學習和使用 PDO. 但如果你需要使用 MySQL 所特有的高級功能,那麼你可能需要嘗試一下 MySQLi, 因為 PDO 為了能夠同時在多種數據庫上使用,不會包含那些 MySQL 獨有的功能。 MySQLi 是 MySQL 的增強接口,同時提供面向過程和面向對象接口,也是目前推薦的 MySQL 驅動,舊的C風格 MySQL 接口將會在今後被默認關閉。 MySQLi 的用法和以上兩段代碼相比,沒有太多新概念,在此不再給出示例,可以參見 PHP 官網文檔 [注]。 注:http://www.php.net/manual/en/mysqli.quickstart.php 類型約束 通過類型約束可以限制參數的類型,不過這一機制並不完善,目前僅適用於類和 callable(可執行類型) 以及 array(數組), 不適用於 string 和 int. 代碼如下:// 限制第一個參數為 MyClass, 第二個參數為可執行類型,第三個參數為數組 function MyFunction(MyClass $a, callable $b, array $c) { // ... } PHP5.2(2006-2011):JSON 支持 包括 json_encode(), json_decode() 等函數,JSON 算是在 Web 領域非常常用的數據交換格式,可以被 JS 直接支持,JSON 實際上是 JS 語法的一部分。 JSON 系列函數,可以將 PHP 中的數組結構與 JSON 字符串進行轉換: 代碼如下:$array = ["key" => "value", "array" => [1, 2, 3, 4]]; $json = json_encode($array); echo "{$json}n"; $object = json_decode($json); print_r($object); 輸出: 代碼如下:{"key":"value","array":[1,2,3,4]} stdClass Object ( [key] => value [array] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) ) 值得注意的是 json_decode() 默認會返回一個對象而非數組,如果需要返回數組需要將第二個參數設置為 true. PHP5.3(2009-2012) PHP5.3 算是一個非常大的更新,新增了大量新特征,同時也做了一些不向下兼容的修改。 【PHP5.3棄用的功能】:以下幾個功能被棄用,若在配置文件中啟用,則 PHP 會在運行時發出警告。 Register Globals 這是 php.ini 中的一個選項(register_globals), 開啟後會將所有表單變量($_GET和$_POST)注冊為全局變量. 看下面的例子: 代碼如下:if(isAuth()) $authorized = true; if($authorized) include("page.php"); 這段代碼在通過驗證時,將 $authorized 設置為 true. 然後根據 $authorized 的值來決定是否顯示頁面. 但由於並沒有事先把 $authorized 初始化為 false, 當 register_globals 打開時,可能訪問 /auth.php?authorized=1 來定義該變量值,繞過身份驗證。 該特征屬於歷史遺留問題,在 PHP4.2 中被默認關閉,在 PHP5.4 中被移除。 Magic Quotes 對應 php.ini 中的選項 magic_quotes_gpc, 這個特征同樣屬於歷史遺留問題,已經在 PHP5.4 中移除。 該特征會將所有用戶輸入進行轉義,這看上去不錯,在第一章我們提到過要對用戶輸入進行轉義。 但是 PHP 並不知道哪些輸入會進入 SQL , 哪些輸入會進入 Shell, 哪些輸入會被顯示為 HTML, 所以很多時候這種轉義會引起混亂。 Safe Mode 很多虛擬主機提供商使用 Safe Mode 來隔離多個用戶,但 Safe Mode 存在諸多問題,例如某些擴展並不按照 Safe Mode 來進行權限控制。 PHP官方推薦使用操作系統的機制來進行權限隔離,讓Web服務器以不同的用戶權限來運行PHP解釋器,請參見第一章中的最小權限原則. 【PHP5.3的新增、改進】 匿名函數 也叫閉包(Closures), 經常被用來臨時性地創建一個無名函數,用於回調函數等用途。 代碼如下:$func = function($arg) { print $arg; }; $func("Hello World"); 以上代碼定義了一個匿名函數,並賦值給了 $func. 可以看到定義匿名函數依舊使用 function 關鍵字,只不過省略了函數名,直接是參數列表。 然後我們又調用了 $func 所儲存的匿名函數。 匿名函數還可以用 use 關鍵字來捕捉外部變量: 復制代碼 代碼如下:function arrayPlus($array, $num) { array_walk($array, function(&$v) use($num){ $v += $num; }); } 上面的代碼定義了一個 arrayPlus() 函數(這不是匿名函數), 它會將一個數組($array)中的每一項,加上一個指定的數字($num). 在 arrayPlus() 的實現中,我們使用了 array_walk() 函數,它會為一個數組的每一項執行一個回調函數,即我們定義的匿名函數。 在匿名函數的參數列表後,我們用 use 關鍵字將匿名函數外的 $num 捕捉到了函數內,以便知道到底應該加上多少。 魔術方法:__invoke(), __callStatic() PHP 的面向對象體系中,提供了若干“魔術方法”,用於實現類似其他語言中的“重載”,如在訪問不存在的屬性、方法時觸發某個魔術方法。 隨著匿名函數的加入,PHP 引入了一個新的魔術方法 __invoke(). 該魔術方法會在將一個對象作為函數調用時被調用: 代碼如下:class A { public function __invoke($str) { print "A::__invoke(): {$str}"; } } $a = new A; $a("Hello World"); 輸出毫無疑問是: