PHP 8.0重大版本更新正式釋出:支援JIT編譯器,效能提升高達3倍

ai52learn發表於2020-11-30

美國時間 11 月 26 日,PHP 團隊宣佈 PHP 8.0 正式 GA。PHP 8.0 是 PHP 語言的最新主要版本,帶來了許多新特性和優化,包括命名引數(named arguments)、聯合型別(union types)、屬性(attributes)、構造器屬性提升(constructor property promotion)、Match 表示式、nullsafe 運算子、JIT,以及針對型別系統、錯誤處理和一致性的諸多改進。

PHP 8.0.0 下載地址:

https://www.php.net/downloads

下文將對新版本的重要亮點做簡單介紹:

命名引數

https://wiki.php.net/rfc/named_params

PHP 7

htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

PHP 8

htmlspecialchars($string, double_encode: false);
  • 僅指定必需引數,跳過可選引數。

  • 引數與順序無關,且是自描述的。

屬性

現在,開發者可以使用基於 PHP 原生語法的結構化後設資料來代替 PHPDoc 註解。

https://wiki.php.net/rfc/attributes_v2

PHP 7

class PostsController
{
  /**
   * @Route("/api/posts/{id}", methods={"GET"})
   */
  public function get($id) { /* ... */ }
}

PHP 8

class PostsController
{
  #[Route("/api/posts/{id}", methods: ["GET"])]
  public function get($id) { /* ... */ }
}

構造器屬性提升

新版本定義和初始化屬性所用的樣板程式碼更少。

https://wiki.php.net/rfc/constructor_promotion

PHP 7

class Point {
  public float $x;
  public float $y;
  public float $z;
  public function __construct(
   float $x = 0.0,
   float $y = 0.0,
   float $z = 0.0,
  ) {
   $this->x = $x;
   $this->y = $y;
   $this->z = $z;
 }
}

PHP 8

class Point {
  public function __construct(
   public float $x = 0.0,
   public float $y = 0.0,
   public float $z = 0.0,
 ) {}
}

聯合型別(Union Types)

Union Types 支援接收多個不同型別的值,而不是單個型別。目前 PHP 已經支援兩種特殊的聯合型別:

  • Type 或 null,使用特殊?Type 語法。

  • array 或 Traversable,使用特殊 iterable 型別。

對於型別組合,可以使用在執行時經過驗證的原生聯合型別宣告來代替 PHPDoc 註解。

https://wiki.php.net/rfc/union_types_v2

支援聯合型別之後,將會允許將更多型別資訊從 phpdoc 遷移至函式簽名。可以說,泛型之後,聯合型別是目前型別宣告系統中最大的突破口。

PHP 7

class Number {
  /** @var int|float */
  private $number;
  /**
   * @param float|int $number
   */
  public function __construct($number) {
   $this->number = $number;
 }
}
new Number('NaN'); // Ok

PHP 8

class Number {
  public function __construct(
   private int|float $number
  ) {}
}
new Number('NaN'); // TypeError

Match 表示式

新的 match 很像 switch,並具有以下特性:

  • Match 是一個表示式,表示其結果可以儲存在變數中或返回。

  • Match 分支僅支援單行表示式,不需要 break; 語句。

  • Match 執行嚴格比較。

https://wiki.php.net/rfc/match_expression_v2

PHP 7

switch (8.0) {
  case '8.0':
   $result = "Oh no!";
   break;
  case 8.0:
   $result = "This is what I expected";
   break;
}
echo $result;
//> Oh no!

PHP 8

echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

Nullsafe 運算子

現在,開發者可以使用帶有新的 nullsafe 運算子的呼叫鏈來代替 null check。當對鏈中一個元素的求值失敗時,整個鏈的執行將中止,並且整個鏈的求值為 null。

https://wiki.php.net/rfc/nullsafe_operator

PHP 7

$country = null;
if ($session !== null) {
  $user = $session->user;
 if ($user !== null) {
   $address = $user->getAddress();
  if ($address !== null) {
    $country = $address->country;
  }
 }
}

PHP 8

$country = $session?->user?->getAddress()?->country;

字串與數字的判斷更合理

使用 == 和其他非嚴格比較運算子對字串和數字之間做比較時,原本的做法是將字串強制轉換為數字,然後對整數或浮點數進行比較。這會導致許多令人驚訝的比較結果,其中最值得注意的是0 == "foobar"返回 true。

在新版本中,僅在字串實際為數字時才使用數字比較,否則將數字轉換為字串,並執行字串比較。

https://wiki.php.net/rfc/string_to_number_comparison

PHP 7

0 == 'foobar' // true

PHP 8

0 == 'foobar' // false

內部函式的型別錯誤一致

在新版本中,如果引數驗證失敗,大多數內部函式將丟擲 Error 異常。

https://wiki.php.net/rfc/consistent_type_errors

PHP 7

strlen([]); // Warning: strlen() expects parameter 1 to be string, array given
array_chunk([], -1); // Warning: array_chunk(): Size parameter expected to be greater than 0

PHP 8

strlen([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk([], -1); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0

JIT 編譯

PHP 8 引入了兩個 JIT 編譯引擎。Tracing JIT 的表現最出色,它在綜合基準測試中的效能提高到大約 3 倍,在某些特定的傳統應用程式中提高到 1.5–2 倍。典型的應用程式效能與 PHP 7.4 相當。

JIT 對 PHP 8 效能的貢獻

型別系統和錯誤處理方面的改進

  • 對算術 / 按位運算子進行更嚴格的型別檢查(https://wiki.php.net/rfc/arithmetic_operator_type_checks)

  • 抽象特徵方法驗證(https://wiki.php.net/rfc/abstract_trait_method_validation)

  • 魔術方法的正確簽名(https://wiki.php.net/rfc/magic-methods-signature)

  • 重分類引擎警告(https://wiki.php.net/rfc/engine_warnings)

  • 不相容方法簽名的致命錯誤(https://wiki.php.net/rfc/lsp_errors)

  • @運算子不再使致命錯誤靜默。

  • 用私有方法繼承(https://wiki.php.net/rfc/inheritance_private_methods)

  • 混合型別(https://wiki.php.net/rfc/mixed_type_v2)

  • 靜態返回型別(https://wiki.php.net/rfc/static_return_type)

  • 內部函式型別(https://externals.io/message/106522)

  • 不透明的物件代替 Curl、Gd、Sockets、OpenSSL、XMLWriter 和 XML 擴充套件的資源

其他語法調整和改進

  • 在引數列表(https://wiki.php.net/rfc/trailing_comma_in_parameter_list)和使用閉包的列表(https://wiki.php.net/rfc/trailing_comma_in_closure_use_list)中允許結尾逗號

  • non-capturing 捕獲(https://wiki.php.net/rfc/non-capturing_catches)

  • 變數語法調整(https://wiki.php.net/rfc/variable_syntax_tweaks)

  • 將名稱空間名稱視為單個令牌(https://wiki.php.net/rfc/namespaced_names_as_token)

  • Throw 現在是表示式(https://wiki.php.net/rfc/throw_expression)

  • 在物件上允許::class(https://wiki.php.net/rfc/class_name_literal_on_object)

新的類、介面和函式

  • Weak Map 類(https://wiki.php.net/rfc/weak_maps)

  • Stringable 介面(https://wiki.php.net/rfc/stringable)

  • str_contains()、str_starts_with()、str_ends_with()(https://wiki.php.net/rfc/str_contains)

  • fdiv()(https://github.com/php/php-src/pull/4769)

  • get_debug_type()(https://wiki.php.net/rfc/get_debug_type)

  • get_resource_id()(https://github.com/php/php-src/pull/54270

  • token_get_all() 物件實現(https://wiki.php.net/rfc/token_as_object)

    下載    

要下載 PHP 8 的原始碼,請訪問下載頁面:

https://www.php.net/downloads

Windows 二進位制檔案位於 Windows 版 PHP 網站:

http://windows.php.net/download

更改列表位於 ChangeLog:

http://www.php.net/ChangeLog-8.php

PHP 手冊中提供了遷移指南。請查閱它以獲取新特性細節和向後不相容更改的詳細列表。

https://www.php.net/manual/en/migration80.php

 延伸閱讀

https://www.php.net/releases/8.0/en.php

相關文章