之前陸續介紹了PHP 5.3的一些新特性,正好上周看到ZendCon關於5.3的PPT,介紹的更為詳細,那麼這裡做個歸總或者說翻譯:)
Namespaces
PHP 5.3最大的改動,毫無疑問就是Namespaces(此前有一篇相關的PHP Namespaces FAQ)。這給PHP開發人員帶來的好處不少,廣為人們所诟病的函數命名問題也得到了解決。
代碼更清晰
5.3之前常見的代碼,需要自定義前綴區分函數和類名
PLAIN TEXT
CODE:
-
function MY_wrapper() {}
-
class MY_DB { }
-
define('MY_CONN_STR', '');
-
MY_wrapper();
-
new MY_DB();
-
MY_CONN_STR;
使用名稱空間之後,代碼看上去更加clean。
PLAIN TEXT
CODE:
-
namespace MY;
-
function wrapper() {}
-
class DB { }
-
const CONN_STR = '';
-
use MY AS MY;
-
wrapper();
-
new DB();
-
CONN_STR;
一個文件中定義了多個namespace
如果一個文件中定義了多個namespace,應該怎樣處理?
PLAIN TEXT
CODE:
-
namespace LIB;
-
class MySQL {}
-
class SQLite {}
-
$b = new SQLite();
-
namespace LIB_EXTRA;
-
class MScrypt {}
-
$a = new MScrypt();
-
var_dump(
-
get_class($a),
-
get_class($b)
-
);
以上代碼輸出為:
PLAIN TEXT
CODE:
-
string(18) "LIB_EXTRA::MScrypt"
-
string(11) "LIB::SQLite"
PHP是解釋執行的語言,以上結果合情合理。
namespace的優先級
namespace中定義的函數,類和常量優先,其次才是全局的。
PLAIN TEXT
CODE:
-
namespace foo;
-
function strlen($foo) { return HtmlentitIEs($foo); }
-
echo strlen("test"); // test
-
echo ::strlen("test"); // 4
-
echo namespace::strlen("test"); // test
namespace和autoload的友情
- autoload會根據namespace名稱以及class名稱來解析類文件位置
- 僅當namespace和全局范圍都沒找到class定義的情況下,autoload才會被觸發
- 在namespace中定義的__autoload不會被自動調用
PLAIN TEXT
CODE:
-
function __autoload($var) { var_dump($var); } // LIB::foo
-
require "./ns.PHP"; /*
-
<?PHP
-
namespace LIB;
-
new foo();
-
*/
namespace一些輔料
PLAIN TEXT
CODE:
-
namespace really::long::pointlessly::verbose::ns;
-
__NAMESPACE__; // 新增的魔法常量,表示當前namespace名稱
-
class a{}
-
get_class(new a()); // really::long::pointlessly::verbose::ns::a
-
use really::long::pointlessly::verbose::ns::a AS b; // 從名稱空間中引用一個類
注:這裡的內容節選自pdf Introduction to PHP 5.3 Slides,後文不再復述。
性能提升
PHP 5.3的總體性能提升了5 - 15%
- md5()快了10-15%
- Better stack implementation in the engine
- Constants移到read-only內存裡
- exception處理過程改進(簡化,opcodes更少)
- (require/include)_once改進,去掉重復open
- Smaller binary size & startup size with gcc4
新語言特性
__DIR__
在5.3以前,為了獲得當前腳本的目錄,需要一次函數調用
PLAIN TEXT
CODE:
-
echo dirname(__FILE__); // < PHP 5.3
在5.3,只需要一個魔術常量__DIR__就解決了。
PLAIN TEXT
CODE:
-
echo __DIR__; // >= PHP 5.3
?:操作符
便捷的?:操作符,可以從兩個值/表達式中快速取得非空值。
PLAIN TEXT
CODE:
-
$a = true ?: false; // true
-
$a = false ?: true; // true
-
$a = "" ?: 1; // 1
-
$a = 0 ?: 2; // 2
-
$a = array() ?: array(1); // array(1);
-
$a = strlen("") ?: strlen("a"); // 1
__callStatic()
新增了魔術方法__callStatic,功能和__call類似,但是僅對static方法有效。
PLAIN TEXT
CODE:
-
class helper {
-
static function __callStatic($name, $args) {
-
echo $name.'('.implode(',', $args).')';
-
}
-
}
-
helper::test("foo","bar"); // test(foo,bar)
動態調用static方法
動態的調用靜態方法?動靜結合。
PLAIN TEXT
CODE:
-
class helper {
-
static function foo() { echo __METHOD__; }
-
}
-
$a = "helper";
-
$b = "foo";
-
$a::$b(); // helper::foo
Late Static Binding
不知道怎麼譯,可能留個原文更容易理解。靜態方法的事件處理時機有變化,以前是在編譯期處理,現在是執行期間處理。
在PHP 5.3之前,下面的代碼會輸出一個A,但是這不是咱們要的,whoami方法已經在class B中重新定義,它本該輸出B才符合咱們想當然的思維。
PLAIN TEXT
CODE:
-
class A {
-
public static function whoami() {
-
echo __CLASS__;
-
}
-
public static function identity() {
-
self::whoami();
-
}
-
}
-
class B extends A {
-
public static function whoami() {
-
echo __CLASS__;
-
}
-
}
-
B::identity(); // A <-- PHP <5.3
下面代碼中使用了static::whoami()來調用靜態方法。PHP 5.3之後,由於__CLASS__是在執行期被處理,那麼這個例子中能順利抓到class B。
PLAIN TEXT
CODE:
-
class A {
-
public static function whoami() {
-
echo __CLASS__;
-
}
-
public static function identity() {
-
static::whoami();
-
}
-
}
-
class B extends A {
-
public static function whoami() {
-
echo __CLASS__;
-
}
-
}
-
B::identity(); // B <-->= PHP 5.3
MySQLnd
見MySQLnd成為PHP 5.3中的默認MySQL驅動
但是PDO_MySQL暫時還不支持mysqlnd,目前只有MySQL(i)擴展可以用到
之前介紹的PHP 5.3的新特性,都是方便開發人員的東東。下面介紹個很討虛擬主機提供商喜歡的特性。
增強的ini文件支持
- CGI/ FastCGI支持類似.htAccess的INI配置
- 每個目錄下都可以有INI設置,ini的文件名取決於PHP.ini的配置,但是[PATH=/var/www/domain.com], [HOST=www.domain.com]段落的設置用戶不能修改。
- 增強的error handling
- 允許在ini文件中定義變量和常量,可以在程序中直接調用。
附上一段ini文件的例子
PLAIN TEXT
CODE:
-
#用戶自定義的PHP.ini文件名 (.htAccess). 默認是".user.ini"
-
user_ini.filename = ".user.ini"
-
-
#如果要禁用這個特性,設置為空值即可
-
user_ini.filename =
-
-
#用戶自定義的PHP.ini文件TTL時長(time-to-live),單位為秒,我理解為緩存過期時間。默認為300秒
-
user_ini.cache_ttl = 300
-
-
[PATH=/var/www/domain.com]
-
variables_order = GPC
-
safe_mode = 1
-
-
[my variables]
-
somevar = “1234”
-
anothervar = ${somevar} ; anothervar == somevar
-
-
[ini arrays]
-
foo[bar] = 1
-
foo[123] = 2
-
foo[] = 3