截至目前(2014.2), PHP 的最新穩定版本是 PHP5.5, 但有差不多一半的用戶仍在使用已經不在維護 [注] 的 PHP5.2, 其余的一半用戶在使用 PHP5.3 [注].
因為 PHP 那“集百家之長”的蛋疼語法,加上社區氛圍不好,很多人對新版本,新特征並無興趣。
本文將會介紹自 PHP5.2 起,直至 PHP5.6 中增加的新特征。
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 函數. // 連接到服務器,選擇數據庫
$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.
// 連接到數據庫
$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. // 限制第一個參數為 MyClass, 第二個參數為可執行類型,第三個參數為數組
function MyFunction(MyClass $a, callable $b, array $c)
{
// ...
}
$array = array("key" => "value", "array" => 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.
if(isAuth())
$authorized = true;
if($authorized)
include("page.php");
這段代碼在通過驗證時,將 $authorized 設置為 true. 然後根據 $authorized 的值來決定是否顯示頁面. $func = function($arg)
{
print $arg;
};
$func("Hello World");
以上代碼定義了一個匿名函數,並賦值給了 $func. function arrayPlus($array, $num)
{
array_walk($array, function(&$v) use($num){
$v += $num;
});
}
上面的代碼定義了一個 arrayPlus() 函數(這不是匿名函數), 它會將一個數組($array)中的每一項,加上一個指定的數字($num). class A
{
public function __invoke($str)
{
print "A::__invoke(): {$str}";
}
}
$a = new A;
$a("Hello World");
輸出毫無疑問是:
A::__invoke(): Hello World__callStatic() 則會在調用一個不存在的靜態方法時被調用。
<?php
// 命名空間的分隔符是反斜槓,該聲明語句必須在文件第一行。
// 命名空間中可以包含任意代碼,但只有 **類, 函數, 常量** 受命名空間影響。
namespace XXOO\Test;
// 該類的完整限定名是 \XXOO\Test\A , 其中第一個反斜槓表示全局命名空間。
class A{}
// 你還可以在已經文件中定義第二個命名空間,接下來的代碼將都位於 \Other\Test2 .
namespace Other\Test2;
// 實例化來自其他命名空間的對象:
$a = new \XXOO\Test\A;
class B{}
// 你還可以用花括號定義第三個命名空間
namespace Other {
// 實例化來自子命名空間的對象:
$b = new Test2\B;
// 導入來自其他命名空間的名稱,並重命名,
// 注意只能導入類,不能用於函數和常量。
use \XXOO\Test\A as ClassA
}
更多有關命名空間的語法介紹請參見官網 [注].
spl_autoload_register(
function ($class) {
spl_autoload(str_replace("\\", "/", $class));
}
);
當你實例化一個類 \XXOO\Test\A 的時候,這個類的完整限定名會被傳遞給 autoload 函數,autoload 函數將類名中的命名空間分隔符(反斜槓)替換為斜槓,並包含對應文件。 class A
{
public function callFuncXXOO()
{
print $this->funcXXOO();
}
public function funcXXOO()
{
return "A::funcXXOO()";
}
}
class B extends A
{
public function funcXXOO()
{
return "B::funcXXOO";
}
}
$b = new B;
$b->callFuncXXOO();
輸出是:
B::funcXXOO可以看到,當在 A 中使用 $this->funcXXOO() 時,體現了“虛函數”的機制,實際調用的是 B::funcXXOO().
class A
{
static public function callFuncXXOO()
{
print self::funcXXOO();
}
static public function funcXXOO()
{
return "A::funcXXOO()";
}
}
class B extends A
{
static public function funcXXOO()
{
return "B::funcXXOO";
}
}
$b = new B;
$b->callFuncXXOO();
情況就沒這麼樂觀了,輸出是:
A::funcXXOO()
這是因為 self 的語義本來就是“當前類”,所以 PHP5.3 給 static 關鍵字賦予了一個新功能:後期靜態綁定:
class A
{
static public function callFuncXXOO()
{
print static::funcXXOO();
}
// ...
}
// ...
這樣就會像預期一樣輸出了:
B::funcXXOO
$name = "MyName";
echo <<< TEXT
My name is "{$name}".
TEXT;
Heredoc 以三個左尖括號開始,後面跟一個標識符(TEXT), 直到一個同樣的頂格的標識符(不能縮進)結束。 var_dump(<<<EOD
Hello World
EOD
);
class A
{
const xx = <<< EOD
Hello World
EOD;
public $oo = <<< EOD
Hello World
EOD;
}
Nowdoc 的行為像一個單引號字符串,不能在其中嵌入變量,和 Heredoc 唯一的區別就是,三個左尖括號後的標識符要以單引號括起來:
$name = "MyName";
echo <<< 'TEXT'
My name is "{$name}".
TEXT;
輸出: My name is "{$name}".
define("XOOO", "Value");
新式風格:
const XXOO = "Value";const 形式僅適用於常量,不適用於運行時才能求值的表達式:
// 正確
const XXOO = 1234;
// 錯誤
const XXOO = 2 * 617;
echo $a ? $a : "No Value";可簡寫成
echo $a ?: "No Value";即如果省略三元運算符的第二個部分,會默認用第一個部分代替。
require("xxoo.phar");
require("phar://xxoo.phar/xo/ox.php");
更多信息請參見官網 [注]. <?php
// Code...
?>
通常就是上面的形式,除此之外還有一種簡寫形式:
<? /* Code... */ ?>還可以把
<?php echo $xxoo;?>簡寫成
<?= $xxoo;?>這種簡寫形式被稱為 Short Open Tag, 在 PHP5.3 起被默認開啟,在 PHP5.4 起總是可用。
// 原來的數組寫法
$arr = array("key" => "value", "key2" => "value2");
// 簡寫形式
$arr = ["key" => "value", "key2" => "value2"];
// Traits不能被單獨實例化,只能被類所包含
trait SayWorld
{
public function sayHello()
{
echo 'World!';
}
}
class MyHelloWorld
{
// 將SayWorld中的成員包含進來
use SayWorld;
}
$xxoo = new MyHelloWorld();
// sayHello() 函數是來自 SayWorld 構件的
$xxoo->sayHello();
Traits還有很多神奇的功能,比如包含多個Traits, 解決沖突,修改訪問權限,為函數設置別名等等。
php -S localhost:8000這樣就在當前目錄建立起了一個Web服務器,你可以通過 http://localhost:8000/ 來訪問。
php -S localhost:8000 index.php這樣一來,所有的請求都會由index.php來處理。
$func = "funcXXOO";
A::{$func}();
新增在實例化時訪問類成員的特征:
(new MyClass)->xxoo();新增支持對函數返回數組的成員訪問解析(這種寫法在之前版本是會報錯的):
print func()[0];
function number10()
{
for($i = 1; $i <= 10; $i += 1)
yield $i;
}
該函數的返回值是一個數組:
$array = [
[1, 2, 3],
[4, 5, 6],
];
foreach ($array as list($a, $b, $c))
echo "{$a} {$b} {$c}\n";
結果:
1 2 3
4 5 6
const A = 2;
const B = A + 1;
class C
{
const STR = "hello";
const STR2 = self::STR + ", world";
}
允許常量作為函數參數默認值:
function func($arg = C::STR2)
function add(...$args)
{
$result = 0;
foreach($args as $arg)
$result += $arg;
return $result;
}
同時可以在調用函數時,把數組展開為函數參數:
$arr = [2, 3];
add(1, ...$arr);
// 結果為 6
namespace Name\Space {
const FOO = 42;
function f() { echo __FUNCTION__."\n"; }
}
namespace {
use const Name\Space\FOO;
use function Name\Space\f;
echo FOO."\n";
f();
}
(摘自http://www.thinkphp.cn/document/474.html)
更多詳情關注官方手冊:http://www.php.net/manual/zh/migration55.php