PHP 5.4中的新特性及被棄用的功能函數概述總結:
一、PHP5.4新增特性
1. 記憶體和效能改進:大型 PHP 應用程式中可節省 20-50% 的記憶體。通過各種最佳化使效能提高 10-30%
2. 支援特性Trait
3. 精簡數組文法,可以定義短數組
4. 函數數組解除引用,支援Array dereferencing,
5. 執行個體方法調用
6. 閉包綁定
7. 對象即函數
8. 內建 Web 服務器 (CLI)
9. 原生會話處理常式介面
10. JsonSerializable 介面
11. 二進位標記法
12. 改進了錯誤訊息
13. 數組到字串轉換通知
14. 函數類型提示的增強,(Callable typehint)
15. 對時間統計的增強,高精度計時器
16. 上傳進度條Upload progress
17. Zend Signal in PHP 5.4
18. PHP 5.4 由Arnaud 引入了一個對三元式的最佳化方案.
1)棄用: allow_call_time_pass_reference、define_syslog_variables、highlight.bg、register_globals、register_long_arrays、magic_quotes、safe_mode、zend.ze1_compatibility_mode、session.bug_compat42、session.bug_compat_warn 以及 y2k_compliance。
2)不再支援PHP 中的 break 和continue 後帶變數文法
3)mysqlnd 這一捆綁的 MySQL 原生驅動程式庫現在預設用於與 MySQL 通訊的各種擴充,除非在編譯時間通過 ./configure 被顯式覆蓋。
以下是您升級到 5.4 時將看到的主要特性:
1. 記憶體和效能改進
許多內部結構已變得更小或完全消失,從而在大型 PHP 應用程式中可節省 20-50% 的記憶體。通過各種最佳化使效能提高 10-30%(主要取決於代碼執行的操作),這些最佳化包括內聯各種常見代碼路徑、將 $GLOBALS 添加到 JIT、“@”操作符運算更快、添加了運行時類/函數/常量緩衝、運行時字串常量現在被拘留、通過預先計算的散列更快地訪問常量、空數組速度更快並使用更少記憶體、unserialize() 和 FastCGI 請求處理速度更快,以及在整個代碼中進行更多的記憶體和效能調整。
例如,早期的一些測試表明,Zend Framework 在 5.4 中運行速度提高 21% 並且記憶體使用量減少 23%,而 Drupal 記憶體使用量減少 50% 並且運行速度大約提高 7%。
2. 支援特性Trait
Trait 可能是 PHP 5.4 中談論最多的特性 — 將它們視為編譯器輔助的複製粘貼。Trait 也是 Scala 的一個特性。其他語言可能將它們稱為“mixin”— 或者這些語言根本不對它們進行命名,但具有擴充介面機制,允許介面包含其方法的實際實現。
與 mixin 相反,PHP 中的 trait 包括顯式衝突解決機制,用於多個 trait 實現相同方法的情況。
trait Singleton { public static function getInstance() { ... } } class A { use Singleton; // ... } class B extends ArrayObject { use Singleton; // ... } // Singleton method is now available for both classes A::getInstance(); B::getInstance();
請參見 php.net/traits 瞭解更多樣本,包括衝突解決文法、方法優先順序、可見度以及對 trait 中常量和屬性的支援。此外,要詳細瞭解概念理論,您可以閱讀 Nathan Schärli 的論文“Trait:行為構建塊中的組合類別”。
3. 精簡數組文法
新增的一種簡單但非常流行的文法:
$a = [1, 2, 3]; $b = ['foo' => 'orange', 'bar' => 'apple'];
就是說,您現在不再需要使用“array”關鍵字來定義數組。
4. 函數數組解除引用,支援Array dereferencing,
1)新增的另一種常用文法。返回數組的函數調用現在可以直接解除引用:
function fruits() { return ['apple', 'banana', 'orange']; } echo fruits()[0]; // Outputs: apple
2)有了Array dereferencing, 以前的這種寫法就再也不必要了:
取而代之的是:
$name = explode(",", "b, x")[0];
另外, Array derefencing也可以出現再指派陳述式的左值中, 也就是理論上你可以這麼寫:
explode(",", "test1, test2")[3] = "phper";
5. 執行個體方法調用
與函數數組解除引用相關,您現在可以調用對象執行個體化方法。與早期版本一樣,您當然仍可以連結方法調用,因此您現在可以編寫如下代碼:
class foo { public $x = 1; public function getX() { return $this->x; } public function setX($val) { $this->x = $val; return $this; } } $X = (new foo)->setX(20)->getX(); echo $X; // 20
然而,由於可能丟棄執行個體化的對象,因此,除非您的建構函式執行有用操作,否則您應該在此改用靜態方法調用。如果將它與精簡數組文法和函數數組解除引用結合使用,我們可以編寫某些十分複雜的代碼:
class foo extends ArrayObject { public function __construct($arr) { parent::__construct($arr); } } echo (new foo( [1, [4, 5], 3] ))[1][0];
看一眼之後,您可以斷定輸出是什麼嗎?在此,我們將二維數組傳遞到僅返回數組的建構函式。然後,我們選出第二個維度第一個元素,因此這將輸出“4”。
6. 閉包綁定
在類執行個體中通過$this引用一個匿名函數(也叫閉包函數)
閉包是在 PHP 5.3 中引入的,但在 5.4 中我們改進了閉包與對象的互動方式。例如:
class Foo { private $prop; function __construct($prop) { $this->prop = $prop; } public function getPrinter() { return function() { echo ucfirst($this->prop); }; } } $a = new Foo('bar');; $func = $a->getPrinter(); $func(); // Outputs: Bar
注意閉包訪問 $this->prop 這一私人屬性。預設情況下,PHP 中的閉包使用預綁定 — 這意味著閉包內的變數具有定義閉包時所具有的值。可以使用引用將其轉換為後綁定。但是,也可以重新綁定閉包:
$a = new Foo('bar'); $b = new Foo('pickle'); $func = $a->getPrinter(); $func(); // Outputs: Bar $func = $func->bindTo($b); $func(); // Outputs: Pickle
在此,我們將閉包從 $a 執行個體重新綁定到 $b 中的執行個體。如果您不希望閉包隨時訪問對象執行個體,可以將閉包聲明為靜態:
class Foo { private $prop; function __construct($prop) { $this->prop = $prop; } public function getPrinter() { return static function() { echo ucfirst($this->prop); }; } } $a = new Foo('bar');; $func = $a->getPrinter(); $func(); // Fatal error: Using $this when not in object context
7. 對象即函數
有一種新的神奇方法,名為“__invoke”,其用法如下:
class MoneyObject { private $value; function __construct($val) { $this->value = $val; } function __invoke() { return sprintf('$%.2f',$this->value); } } $Money = new MoneyObject(11.02/5*13); echo $Money(); // Outputs: $28.65
8. 內建 Web 服務器 (CLI)
CLI 伺服器是一種小型 Web 服務器實現,可以從命令列運行:
% php -S localhost:8000 PHP 5.4.0 Development Server started at Sun Mar 11 13:27:09 2012 Listening on localhost:8080 Document root is /home/rasmus Press Ctrl-C to quit.
CLI 伺服器不適合用作實際執行網頁伺服器;我們將使用它運行一些 PHP 迴歸測試,其他單元測試機制也可使用它,並且 IDE 也可能使用它。它確實具有一些很有用的特性,用於從命令列進行日常代碼調試。預設情況下,它使用目前的目錄作為 DocumentRoot;它也處理靜態檔案請求。預設目錄索引檔案為“index.php”,因此您可以在滿含 .php、.css、.jpg 等檔案的目錄中啟用它,它自己就可以運行。對於可能使用 mod_rewrite 將所有請求發送到前端控制器或路由器的更複雜應用程式,您可以將此路由器與一個簡單的小指令碼封裝在一起,並啟動 CLI 伺服器,如下所示:
% php -S localhost:8080 /path/to/router.php PHP 5.4.0 Development Server started at Sun Mar 11 13:28:01 2012 Listening on localhost:8080 Document root is /tmp/web Press Ctrl-C to quit.
router.php 指令碼可能如下所示:
此封裝器載入直接 .php 請求,將包含“.”的任何其他請求傳遞到靜態檔案處理常式,其他所有內容都傳遞到架構的路由器。您可以如此直接從命令列運行 Drupal 和 Symphony。
9. 原生會話處理常式介面
這是一個小而方便的特性,現在可以用它實現會話處理常式介面。現在,您可以僅將會話處理對象的執行個體傳遞給 session_set_save_handler(),而不必傳遞給它六個比較麻煩的函數:
SessionHandler implements SessionHandlerInterface { public int close ( void ) public int destroy ( string $sessionid ) public int gc ( int $maxlifetime ) public int open ( string $save_path , string $sessionid ) public string read ( string $sessionid ) public int write ( string $sessionid , string $sessiondata ) } session_set_save_handler(new MySessionHandler);
10. JsonSerializable 介面
現在,您可以通過實現 JsonSerializable 介面來控制有人嘗試使用 json_encode() 對您的對象進行編碼時所發生的情況:
class Foo implements JsonSerializable { private $data = 'Bar'; public function jsonSerialize() { return array('data'=>$this->data); } } echo json_encode(new Foo); // Outputs: {"data":"Bar"}
11. 二進位標記法
為了與 PHP 的原生十六進位和八進位支援協調一致,現在也支援二進位標記法:採用“0b”首碼標識位元
$mask = 0b010101;
12. 改進了錯誤訊息
錯誤訊息稍有改進。
改進前:
% php -r 'class abc foo' Parse error: syntax error, unexpected T_STRING, expecting '{' in Command line code on line 1
改進後:
% php -r 'class abc foo' Parse error: syntax error, unexpected 'foo' (T_STRING), expecting '{' in Command line code on line
改進可能不十分明顯,但區別是現在已在錯誤訊息中顯示位移標記“foo”的值。
13. 數組到字串轉換通知
如果您一直使用 PHP,則可能以隨機出現在頁面中“Array”一詞結束編程,因為您嘗試直接輸出數組。每當將數組直接轉換為字串時,都很有可能出現錯誤,現在有了一個針對這一情況的通知:
$a = [1,2,3]; echo $a;
注意:數組到字串轉換在 example.php onlLine 2 中
14. 函數類型提示的增強,(Callable typehint)
由於php是弱類型的語言,因此在php 5.0後,引入了函數類型提示的功能,支援對象和數組,其含義為對於傳入函數中的參數都進行類型檢查,舉個例子,有如下的類:
class bar { } function foo(bar $foo) { }
其中函數foo中的參數規定了傳入的參數必須為bar類的執行個體,否則系統會判斷出錯。同樣對於數組來說,也可以進行判斷,比如:
function foo(array $foo) { } foo(array ( 1, 2, 3 )); // 正確,因為傳入的是數組 foo(123); // 不正確,傳入的不是數組 function my_function(callable $x) { return $x(); }
而在php 5.4中,則支援對callable類型的支援。在以前, 我們如果希望一個函數接受一個回呼函數作為參數, 那需要做很多額外的工作來檢查是否是可調用的正確的回呼函數,例子如下:
function foo(callable $callback) { }
則:
foo("false"); //錯誤,因為false不是callable類型 foo("printf"); //正確 foo(function () { }); //正確 class A { static function show() { } } foo(array ( "A", "show" )); //正確
遺憾的是,PHP 5.4中,依然不支援對基本類型如字元,整形等的類型提示。
15. 對時間統計的增強,高精度計時器
此次引入了$_SERVER['REQUEST_TIME_FLOAT']陣列變數,微秒級精度(百萬分之一秒,float類型)。對於統計指令碼已耗用時間會非常有用:
echo 'Executed in ', round(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 2)
16. 上傳進度條Upload progress
檔案上傳進度反饋, 這個需求在當前是越來越普遍, 比如大附件郵件. 在PHP5.4以前, 我們可以通過APC提供的功能來實現. 或者使用PECL擴充uploadprogress來實現.
雖然說, 它們能很好的解決現在的問題, 但是也有很明顯的不足:
1. 他們都需要額外安裝(我們並沒有打算把APC加入PHP5.4)
2. 它們都使用本地機制來儲存這些資訊, APC使用共用記憶體, 而uploadprogress使用檔案系統(不考慮NFS), 這在多台前端機的時候會造成麻煩.
從PHP的角度來說, 最好的儲存這些資訊的地方應該是SESSION, 首先它是PHP原生支援的機制. 其次, 它可以被配置到存放到任何地方(支援多機共用).
正因為此, Arnaud Le Blanc提出了針對Session報告上傳進度的RFC, 並且現在實現也已經包含在了PHP5.4的主幹中。
通過$_SESSION["upload_progress_name"]就可以獲得當前檔案上傳的進度資訊,結合Ajax就能很容易實現上傳進度條了。
17. Zend Signal in PHP 5.4
在PHP5.4中, 根據由Rasmus提交的RFC, 引入了一套新的訊號處理機制, 目的是為了使得訊號屏蔽機制可以應用到任何SAPI中, 並且提高在這個過程中的PHP效能.
新的機制, 叫做zend signal, 它的理念, 來自Yahoo的”延遲訊號處理”(Yahoo signal deferring mechanism), 而後, facebook把這套理念加入了PHP中, 為了提升PHP+Apache 1.X下PHP調用ap_block/ap_unblock的效能.
18. PHP 5.4 由Arnaud 引入了一個對三元式的最佳化方案.
我們都知道PHP用寫時複製來對變數複製做效能最佳化, 而在以前的三元式中, 卻每次都會複製, 這在運算元是大數組的情況下, 會造成效能問題:
二、刪除的特性
1)最後,我們集中整理了幾年來標記為已棄用的多個特性。這些特性包括 allow_call_time_pass_reference、define_syslog_variables、highlight.bg、register_globals、register_long_arrays、magic_quotes、safe_mode、zend.ze1_compatibility_mode、session.bug_compat42、session.bug_compat_warn 以及 y2k_compliance。
2) 備受指責的 Register Globals 已從 PHP 中完全刪除。十年來,該特性一直以其頻繁發生的安全性漏洞而著稱。2002年該特性被設定為預設關閉。2009年發布的 PHP5.3 將該特性標記為“棄用”,想必從那時起,大部分開發人員已經不再使用它。
3)除了這些特性之外,magic_quotes 可能是最大的危險。在早期版本中,未考慮因 magic_quotes 出錯導致的後果,簡單編寫且未採取任何舉措使自身免受 SQL 插入式攻擊的應用程式都通過 magic_quotes 來保護。如果在升級到 PHP 5.4 時未驗證已採取正確的 SQLi 保護措施,則可能導致安全性漏洞。
4)PHP 中的 break 和continue 語句之後可以跟上一個參數用來指明跳出的迴圈層數。如果不指定參數,它會像 VB、C#或 Java 一樣跳出最內層的迴圈。在 PHP 5.4 之前,開發人員可以向 break 語句傳遞一個變數,而現在只能傳遞常量。
5)PHP 允許參數按引用傳遞。在早期版本中,你可以通過為調用點添加修飾來指明變數按引用傳遞。在 PHP 5.4 中,該選項已被移除。相反,現代 PHP 編程只需要在函式宣告時指定按引用傳遞即可。與 C# 不同,你不需要同時在聲明和調用點指定按引用傳遞。
三、其他改動和特性
有一種新的“可調用的”類型提示,用於某方法採用回調作為參數的情況。
htmlspecialchars() 和 htmlentities() 現在可更好地支援亞洲字元,如果未在 php.ini 檔案中顯式設定 PHP default_charset,這兩個函數預設使用 UTF-8 而不是 ISO-8859-1。
會話 ID 現在預設通過 /dev/urandom(或等效檔案)中的熵產生,而不是與早期版本一樣成為必須顯式啟用的一個選項。
mysqlnd 這一捆綁的 MySQL 原生驅動程式庫現在預設用於與 MySQL 通訊的各種擴充,除非在編譯時間通過 ./configure 被顯式覆蓋。
可能還有 100 個小的改動和特性。從 PHP 5.3 升級到 5.4 應該極為順暢,但請閱讀遷移指南加以確保。如果您從早期版本升級,執行的操作可能稍多一些。請查看以前的遷移指南再開始升級。
PHP 5.4版本將是最後一個支援Windows XP 和 Windows 2003的版本,今後將不再提供針對這些作業系統的二進位包。