成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

PHP 5.4 中的新特性

2013-05-21 14:42:56來源:Oracle作者:Rasmus Lerdorf

大約八年前,我為 Oracle 技術網寫了一篇名為“您了解 PHP 嗎?”的文章。在那篇文章中,我談到了 PHP 固執的功能優于形式的“Web 問題”解決方法,以及它所具備的讓事情變得簡單的能力。當時,我們即將發布 PHP 5.

大約八年前,我為 Oracle 技術網寫了一篇名為“您了解 PHP 嗎?”的文章。在那篇文章中,我談到了 PHP 固執的功能優于形式的“Web 問題”解決方法,以及它所具備的讓事情變得簡單的能力。當時,我們即將發布 PHP 5.0。現在,時隔將近十年之后我們推出全新的 PHP 5.4.0 版本,雖然在這期間發生了很多事情,但也有許多事情根本沒變。

沒變的一件事情就是生態系統一如以往那樣重要。解決 Web 問題不僅僅關乎腳本語言的選擇,它關乎的是周圍的整個生態系統。現在,LAMP 體系已盛行近 15 年,仍廣受歡迎,但我們開始注意到其他功能強大的方案。附帶 nginx 的 PHP-FPM 已經快速流行起來,因為從 PHP 5.3 開始大大改進了支持,并在 5.4 中進一步得到簡化。體系中的 M(即數據庫)部分與 8 年前相比也開始變得極為不同。與將所有內容都只放入 MyISAM 表中相比,各種 NoSQL 解決方案和 MySQL Cluster 提供了一組更豐富的選擇。

出現了多種有趣的技術,因而我們編寫了 PHP 擴展來輕松訪問這些技術。我最喜愛的一個擴展是 libevent,可以用它在 PHP 中編寫事件驅動的高性能應用程序。另一個是 ZeroMQ,這是一個高級套接字庫。與 SQLite 不再需要編寫另一種原始文件格式和關聯的分析器極為相似,ZeroMQ 也無需因任何理由而使用套接字協議和關聯的套接字處理代碼。您甚至可以組合使用 libevent 和 ZeroMQ,以獲得獨立、高性能、事件驅動的卓越服務器。(如果您對此感興趣,請參見此示例。)我還十分喜歡 SVM(支持向量機)這一機器學習算法,您不必成為機器學習的愛好者也可提出許多問題。

還有許多擴展在最近幾年內已被廣泛接受。特別是,Gearman 變得流行起來,逐漸成為用戶部署的常見體系的一部分。您可以通過 Gearman 分派作業,以便由工作器異步完成這些作業。工作器可以遍布多臺服務器,它們甚至可以進一步分派更多的 MapReduce 類型作業。

2004 年發布 PHP 5.0 之后,接下來在 2005 年推出 5.1,此版本新增了 DateTime 實現、PDO 和性能改進。PHP 5.2 于 2006 年發布,引入了改進的內存管理器、JSON 支持和輸入篩選。當時,我們著手推動 PHP 6,這是一個極其宏偉的計劃,完全重寫有關 ICU(Unicode 國際化組件)庫的所有內容。事實證明這個計劃有些操之過急 — 我們無法使足夠多的開發人員為之興奮,最終只得將準備引入 PHP 6 的各種特性添加到 2009 年發布的 PHP 5.3 中。5.2 與 5.3 版本時隔 3 年,這也意味著 5.3 向 PHP 新增了大量內容:命名空間、后期靜態綁定、閉包、垃圾收集、受限 goto、mysqlnd(MySQL 原生驅動程序)、更好的 Windows 性能以及許多其他內容。

事后看來,將此版本稱為 PHP 6 可能有一定的道理,但 PHP 6 等同于在 Unicode 方面所做的努力,以至于為此編寫了相關書籍,因此我們認為如果沒有對 Unicode 做出重大改進,就不能發布 PHP 6。我們引入了名為“intl”的 ICU 擴展,它也針對 PHP 5.2 編譯,這可讓您訪問更多的 ICU 功能。mbstring 擴展隨時間不斷地改進,這意味著幾乎任何與 Unicode 相關的問題都有解決方案,只是未明確集成到語言本身中。

這樣在 2012 年推出 PHP 5.4。而且,與上一版本時隔將近 3 年,我們在此期間對一些內容進行了改進。我寧愿恢復到每年推出一個版本,每個版本包含更少的新特性。

以下是您升級到 5.4 時將看到的主要特性:

內存和性能改進

許多內部結構已變得更小或完全消失,從而在大型 PHP 應用程序中可節省 20-50% 的內存。通過各種優化使性能提高 10-30%(主要取決于代碼執行的操作),這些優化包括內聯各種常見代碼路徑、將 $GLOBALS 添加到 JIT、“@”操作符運算更快、添加了運行時類/函數/常量緩存、運行時字符串常量現在被拘留、通過預先計算的散列更快地訪問常量、空數組速度更快并使用更少內存、unserialize() 和 FastCGI 請求處理速度更快,以及在整個代碼中進行更多的內存和性能調整。

例如,早期的一些測試表明,Zend Framework 在 5.4 中運行速度提高 21% 并且內存使用減少 23%,而 Drupal 內存使用減少 50% 并且運行速度大約提高 7%。

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:行為構建塊中的組合類”。

精簡數組語法

新增的一種簡單但非常流行的語法:

$a = [1, 2, 3];
$b = ['foo' => 'orange', 'bar' => 'apple'];

就是說,您現在不再需要使用“array”關鍵字來定義數組。

函數數組解除引用

新增的另一種常用語法。返回數組的函數調用現在可以直接解除引用:

function fruits() {
    return ['apple', 'banana', 'orange'];
}
echo fruits()[0]; // Outputs: apple

實例方法調用

與函數數組解除引用相關,您現在可以調用對象實例化方法。與早期版本一樣,您當然仍可以鏈接方法調用,因此您現在可以編寫如下代碼:

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”。

閉包綁定

閉包是在 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

對象即函數

有一種新的神奇方法,名為“__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

內置 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 服務器不適合用作生產 Web 服務器;我們將使用它運行一些 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
if (preg_match('!\.php$!', $_SERVER["REQUEST_URI"])) {
    require basename($_SERVER["REQUEST_URI"]);
} else if (strpos($_SERVER["REQUEST_URI"], '.')) { 
    return false; // serve the requested file as-is.
} else {
    Framework::Router($_SERVER["REQUEST_URI"]); 
}

此包裝器加載直接 .php 請求,將包含“.”的任何其他請求傳遞到靜態文件處理程序,其他所有內容都傳遞到框架的路由器。您可以如此直接從命令行運行 Drupal 和 Symphony。

原生會話處理程序接口

這是一個小而方便的特性,現在可以用它實現會話處理程序接口。現在,您可以僅將會話處理對象的實例傳遞給 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);

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"}

二進制表示法

為了與 PHP 的原生十六進制和八進制支持協調一致,現在也支持二進制表示法:

$mask = 0b010101;

改進了錯誤消息

錯誤消息稍有改進。

改進前:

% 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”的值。

數組到字符串轉換通知

如果您一直使用 PHP,則可能以隨機出現在頁面中“Array”一詞結束編程,因為您嘗試直接輸出數組。每當將數組直接轉換為字符串時,都很有可能出現錯誤,現在有了一個針對這一情況的通知:

$a = [1,2,3];
echo $a;

注意:數組到字符串轉換在 example.php onlLine 2 中

刪除的特性

最后,我們集中整理了幾年來標記為已棄用的多個特性。這些特性包括 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。

除了這些特性之外,magic_quotes 可能是最大的危險。在早期版本中,未考慮因 magic_quotes 出錯導致的后果,簡單編寫且未采取任何舉措使自身免受 SQL 注入攻擊的應用程序都通過 magic_quotes 來保護。如果在升級到 PHP 5.4 時未驗證已采取正確的 SQLi 保護措施,則可能導致安全漏洞。

其他改動和特性

  • 有一種新的“可調用的”類型提示,用于某方法采用回調作為參數的情況。

  • htmlspecialchars() 和 htmlentities() 現在可更好地支持亞洲字符,如果未在 php.ini 文件中顯式設置 PHP default_charset,這兩個函數默認使用 UTF-8 而不是 ISO-8859-1。

  • <?=(精簡回顯語法)現在始終可用,無論 short_tags ini 設置的值為何。這應該使模板化系統創建者感到滿意。

  • 會話 ID 現在默認通過 /dev/urandom(或等效文件)中的熵生成,而不是與早期版本一樣成為必須顯式啟用的一個選項。

  • mysqlnd 這一捆綁的 MySQL 原生驅動程序庫現在默認用于與 MySQL 通信的各種擴展,除非在編譯時通過 ./configure 被顯式覆蓋。

可能還有 100 個小的改動和特性。從 PHP 5.3 升級到 5.4 應該極為順暢,但請閱讀遷移指南加以確保。如果您從早期版本升級,執行的操作可能稍多一些。請查看以前的遷移指南再開始升級。

PHP 的下一步規劃是什么?

我們沒有對 PHP 進行長期規劃。PHP 將隨 Web 一起發展。我們不知道 5-10 年內的重要 Web 趨勢和技術將是什么,但知道通過我們的不斷付出,PHP 必將存在。

短期內,我們通過“internals”郵件列表討論 PHP 開發,并且就大特性達成共識時,它將發展為 RFC。您可以在 wiki.php.net/rfc 中找到 RFC。一旦我們表決同意發布一組極佳的新特性,并且對這些特性進行了正確實現和測試,我們便開始籌備推出新版本。

PHP 隨 Web 發展并保持穩定的市場份額,在全球所有網站中,大約三分之一的網站都使用它。其中不僅包括一些最大的網站,而且還包括很大一部分最小的網站。我是在最小網站上單獨設置 PHP 的:擴展是自然而然的事情,甚至是預期的特征,也是強烈吸引工程師的特征,但縮減不太正常,并且在某些情況下更困難。如果您找到適當的平衡,并且可以將同一代碼庫用于宿舍出租乃至擁有數十億美元資產的公司,那么您就真正掌握了這種語言。

作者介紹

Rasmus Lerdorf 因 1995 年創建 PHP 項目而廣為人知,多年來,為許多其他開源項目做出了卓越貢獻。他在 Yahoo! 擔任基礎架構師的時間已超過 7 年,并在 2012 年加入 Etsy。他出生于格陵蘭島,成長于丹麥和加拿大,并在滑鐵盧大學獲得系統設計工程學位。您可以在 Twitter 上關注 @rasmus。
 

關鍵詞:PHP

贊助商鏈接:

主站蜘蛛池模板: 随州市| 都匀市| 镇江市| 十堰市| 敦煌市| 沁水县| 宣威市| 平武县| 泗阳县| 开原市| 乳源| 宜章县| 衡山县| 柳林县| 巫山县| 乐亭县| 兴山县| 乐都县| 衡山县| 屏东市| 五原县| 集贤县| 西丰县| 江津市| 潜山县| 乌鲁木齐市| 葵青区| 安仁县| 金湖县| 乌鲁木齐县| 阿拉善右旗| 内丘县| 丹寨县| 北票市| 静海县| 石城县| 南岸区| 吉安县| 星子县| 五家渠市| 镇赉县|