9. PHP5.3-5.6 新特性
1. PHP5.3中的新特性
1.1 支援名稱空間(namespace)
毫無疑問,名稱空間是PHP5.3所帶來的最重要的新特性。
在PHP5.3中,可以用名稱空間防止程式碼的衝突,名稱空間的分隔符為 \ 反斜線。
1.2 通過static關鍵字,實現方法的延遲靜態繫結
在PHP中,我們可以在類中通過self關鍵字或者CLASS來判斷或呼叫當前類。但有一個問題,如果我們是在子類中呼叫,得到的結果將是父類。因為在繼承父類的時候,靜態成員就已經被綁定了。例如:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
上面程式碼的輸出結果為:A。這和我們的預期結果不同。
PHP5.3中增加了一個static關鍵字來引用當前類,即實現了延遲靜態繫結:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // 這裡實現了延遲的靜態繫結
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
// 輸出:B
1.3 支援goto語句
多數計算機程式設計語言中都支援無條件轉向語句goto,當程式執行到goto語句時,即轉向由goto語句中的標號指出的程式位置繼續執行。儘管goto語句有可能會導致程式流程不清晰,可讀性減弱,但在某些情況下具有其獨特的方便之處,例如中斷深度巢狀的迴圈和 if 語句。
<?php
goto test;
echo '1';
test:
echo '2';
?>
// 執行時會輸出 2
1.4 支援閉包
閉包(Closure)函式和Lambda函式的概念來自於函式程式設計領域。例如JavaScript 是支援閉包和 lambda 函式的最常見語言之一。
在PHP5.3中,可以使用匿名函式或Lambda函式來定義一些臨時使用(即用即棄型)的函式,以作為array_map()或array_walk()等函式的回撥函式。
1.5 新增兩個魔術方法__callStatic()和__invoke()
PHP中原本有一個魔術方法__call(),當呼叫類中某個不存在的方法時該魔術方法會被自動呼叫。新增的__callStatic()方法則只用於類的靜態方法。當嘗試呼叫類中不存在的靜態方法時,__callStatic()魔術方法將被自動呼叫。
此外,PHP5.3中還新增了__invoke()魔術方法。當嘗試以呼叫函式的方式呼叫一個物件時,__invoke() 方法會被自動呼叫。 如:
<?php
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
/* 輸出結果:
int(5)
bool(true)
*/
1.6 新增Nowdoc語法結構
就象 Heredoc 結構類似於雙引號字串,Nowdoc 結構是類似於單引號字串的。Nowdoc 結構很象 heredoc 結構,但是 nowdoc 中不進行解析操作。故非常適合於傳遞一段PHP程式碼。
<?php
$str = <<<'EOD'
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;
echo $str;
1.7 const 關鍵字可用來在類外定義常量
<?php
//PHP中定義常量通常是用這種方式
define("CONSTANT", "Hello world.");
//PHP5.3中的const關鍵字也支援在類外定義常量
const CONSTANT = 'Hello World';
1.8 三元運算子可以簡寫為省略中間的部分
原本格式為 expr1 ? expr2 : expr3 。
如果expr1結果為True,則返回expr2的結果,否則返回expr3。
PHP5.3新增了一種書寫方式,可以省略中間部分,簡寫為 expr1 ?: expr3 ,當 expr1 為 TRUE 時返回 expr1,否則返回 expr3。
1.9 支援動態訪問類的靜態成員或靜態方法
<?php
class Test{
public static function testgo()
{
echo "gogo!";
}
}
$class = 'Test';
$action = 'testgo';
$class::$action(); //輸出 "gogo!"
1.10 支援try…catch異常捕獲的巢狀
<?php
class MyException extends Exception { }
class Test {
public function testing() {
try {
try {
throw new MyException('foo!');
} catch (MyException $e) {
/* rethrow it */
throw $e;
}
} catch (Exception $e) {
return $e->getMessage();
}
}
}
$foo = new Test;
echo $foo->testing();
// 輸出:foo!
?>
此外,PHP5.3還棄用了一些老版本的功能和函式,並用新的函式進行替代,這裡不做贅述。
2. PHP5.4中的新特性
2.1 新增traits
Traits提供了一種靈活的程式碼重用機制,既不像interface一樣只能定義方法但不能實現,又不像class一樣只能單繼承。
<?php
// Traits不能被單獨例項化,只能被類所包含
trait SayWorld
{ public function sayHello()
{
echo 'World!';
}
}
class MyHelloWorld
{
// 將SayWorld中的成員包含進來
use SayWorld;
}
$xxoo = new MyHelloWorld();
// sayHello() 函式是來自 SayWorld 構件的
$xxoo->sayHello();
2.2 新增短陣列語法
<?php
// 原來的陣列寫法
$arr = array("key" => "value", "key2" => "value2");
$arr = array(1,2,3,4);
// 簡寫形式
$arr = ["key" => "value", "key2" => "value2"];
$arr = [1,2,3,4];
2.3 支援對函式返回陣列的成員訪問解析
<?php
function myfunc() {
return array('jack','rose');
}
// 以前的寫法
$arr = myfunc();
echo $arr[0];
// PHP5.4中,支援這樣書寫
echo myfunc()[0];
2.4 內建了用於開發的 CLI 模式的 web server
//啟動Web伺服器
php -S localhost:8000
//啟動時指定根目錄
php -S localhost:8000 -t /home/me/public_html/foo
//使用路由(Router)指令碼
php -S localhost:8000 index.php //所有的請求都會由index.php來處理。
2.5 支援在例項化時訪問類成員
(new Foo)->bar();
2.6 session提供了上傳進度支援
通過 $_SESSION[“upload_progress_name”] 就可以獲得當前檔案上傳的進度資訊,結合 Ajax 就能很容易的實現上傳進度條。
2.7 讓Json更懂中文(JSON_UNESCAPED_UNICODE)
PHP5.4中的json_encode()函式的第二個引數,新增了一個常量JSON_UNESCAPED_UNICODE,可有效防止中文字元被轉成Unicode編碼格式。
<?php
echo json_encode(array("中文"));
// 輸出:["\u4e2d\u6587"]
echo json_encode(array("中文"), JSON_UNESCAPED_UNICODE);
// 輸出:["中文"]
// 如果第二個引數指定為JSON_UNESCAPED_UNICODE,就不會將中文轉換為Unicode編碼格式
2.8 default_charset從ISO-8859-1變為UTF-8
預設傳送“Content-Type: text/html; charset=utf-8”,你再也不需要在HTML裡寫meta 標籤了,也無需為UTF-8相容而傳送額外的header了。
2.9 新增二進位制直接量
<?php
$bin = bindec('1101'); //之前需要這樣寫
$bin = 0b1101;
echo $bin; // 輸出13
2.10 支援宣告函式的引數型別
<?php
function foo(array $arr) { // 宣告foo函式的引數型別必須是array
echo json_encode($arr);
}
// foo(1); // 這裡會報錯,foo的引數型別必須是array
foo(array(1,2,3)); // 正確
此外,PHP5.4 廢除了register_globals、 magic_quotes、 allow_call_time_pass_reference以及安全模式等等。
在早期版本中,你可以在函式呼叫時,在引數前新增&修飾符來指明引數變數按引用傳遞。但在 PHP 5.4 中,該用法已被移除,你只需要在函式宣告時指定按引用傳遞即可。
<?php
// 早期版本中,要想給一個函式傳遞一個引用,是這樣寫的
/* function foo($a) {
$a = 100;
}
$a = 3;
foo(&$a);
echo $a; */
// 自PHP5.4以後,不能再像上面那樣用,如果還想給一個函式傳遞一個引用,可以在宣告時就指明
function goo(&$a) {
$a = 100;
}
$a = 3;
goo($a);
echo $a; // 輸出:100
3. PHP5.5中的新特性
3.1 新增Generator生成器yield
yield關鍵字用於當函式需要返回一個迭代器的時候,逐個返回值。
<?php
function number10()
{
for($i = 1; $i <= 10; $i += 1) {
yield $i;
}
}
$generatorObj = number10(); // 是一個物件
// var_dump($generatorObj);
foreach ($generatorObj as $i) {
echo $i;
}
// 輸出:12345678910
3.2 try…catch 新增了finally
這和java中的finally一樣,經典的try … catch … finally 三段式異常處理。
不論是否捕獲到異常,finally中的程式碼都會執行。只要finally中有return語句,就以finally的返回值為準;否則,以try或者catch中的返回值為準。
<?php
function foo() {
try {
echo 'success!'.PHP_EOL;
throw new Exception('exception!');
echo 'failed!'.PHP_EOL;
return 1;
} catch (Exception $e) {
echo $e->getMessage().PHP_EOL;
return 2;
} finally {
echo "finally!".PHP_EOL;
return 3;
}
}
echo foo();
// 輸出:success! exception! finally! 3
3.3 foreach中支援巢狀list()結構
對二維陣列進行遍歷,之前可能需要使用兩個foreach,現在只需要使用foreach + list了,但是需確保個數一致。
<?php
$arr = [
[1, 2, 3],
[4, 5, 6]
];
foreach ($arr as list($a, $b, $c)) {
echo $a.$b.$c.'<br>';
}
/*
輸出:
123
456
*/
3.4 empty() 支援傳入表示式,而不僅是一個變數
<?php
function always_false() {
return false;
}
if (empty(always_false())) {
echo 'This will be printed.';
}
3.5 非變數array或string也能支援下標訪問
<?php
echo array(1, 2, 3)[0];
echo [1, 2, 3][0];
echo "foobar"[0];
// 輸出:11f
3.6 新增密碼雜湊API
缺點是缺乏互操作性,在需要和其他語言對接時會比較麻煩。
<?php
$passwd = '123456';
// 加密,將原密碼生成一個hash雜湊值
$hashKey = password_hash($passwd, PASSWORD_DEFAULT); // 每次重新整理,生成的hash雜湊值都不一樣
echo $hashKey,'<br>';
//輸出結果類似於:$2y$10$Z215AkvS1sFVi4syS9no7eGXCa9mBwiH1BviaQzy4Dh4RvL2/JtpK
// 驗證,利用hash雜湊值對原密碼進行驗證
if(password_verify($passwd, $hashKey)) {
echo "密碼正確!";
} else {
echo "密碼錯誤!";
}
3.7 新增 boolval() 函式
PHP已經實現了strval、intval和floatval的函式來進行強制型別轉換。為了達到一致性,PHP5.5新增了boolval函式。
3.8 新增 array_column() 函式
可用來返回二維陣列中指定的列。
<?php
$records = array(
array('id' => 2135,'name' => 'John'),
array('id' => 3245,'name' => 'Smith'),
array('id' => 5342,'name' => 'Peter')
);
//從結果集中取出 name 列
$names = array_column($records, 'name');
print_r($names);
//從結果集中取出 name 列,並用相應的 id 作為鍵
$names = array_column($records, 'name', 'id');
print_r($names);
4. PHP5.6中的新特性
4.1 增強了const 常量
在PHP5.6之前,關鍵字const定義常量時,只能使用固定的值,且值的型別只能是標量。
在PHP5.6中,對const常量進行了增強,允許常量計算,允許使用包含數字、字串字面值和常量的表示式結果來定義const常量。常量的值也可以為一個數組,但不能是變數。
<?php const A = 2; const B = A + 1; const C = "Hello"." Wolrd!"; const D = array(1, 2, 3); define('E', 100); var_dump(A, B, C ,D, E); // 輸出:int(2) int(3) string(12) "Hello Wolrd!" array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } int(100)
4.2 支援使用 … 運算子定義變長引數函式
現在可以不依賴 func_get_args(), 使用 … 運算子來實現變長引數函式。
<?php
function test(...$args)
{
var_dump($args);
}
test(1,2,3);
// 輸出:array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
4.3 支援使用 ** 進行冪運算
加入右連線運算子 * 來進行冪運算。 同時還支援簡寫的 *= 運算子,表示進行冪運算並賦值。
<?php
printf(2 ** 3); // 8
$a = 2;
$a **= 3;
printf($a); // 8
4.4 名稱空間 use 操作符支援函式和常量的匯入
use 運算子可以匯入外部(其他名稱空間)的函式和常量,對應的結構為 use function 和 use const。
<?php
namespace Name\Space {
const FOO = 42;
function f() { return __FUNCTION__; }
}
namespace {
use const Name\Space\FOO;
use function Name\Space\f;
echo '常量:'.FOO;
echo '<br>';
echo '函式:'.f();
}
/*
輸出:
常量:42
函式:Name\Space\f
*/
4.5 新增引數解包功能
在呼叫函式的時候,通過 … 操作符可以把陣列或者可遍歷物件解包到引數列表,這和Ruby等語言中的擴張(splat)操作符類似。
<?php
function add($a, $b, $c) {
return $a + $b + $c;
}
$arr = [2, 3];
echo add(1, ...$arr); // 輸出:6
4.6 支援大檔案上傳
可以上傳超過2G的大檔案。
4.7 php://input 可以被複用
php://input 是個可以訪問請求的原始資料的只讀流。 在 PHP 5.6 之前 php://input 開啟的資料流只能讀取一次; 資料流不支援 seek 操作。 不過,現在依賴於 SAPI 的實現,請求體資料被儲存的時候, 它可以開啟另一個 php://input 資料流並重新讀取。 通常情況下,這種情況只是針對 POST 請求,而不是其他請求方式。