一篇文章幫你瞭解 PHP 7.3 更新

Summer__發表於2019-04-04

file

文章轉自:learnku.com/php/t/21549

PHP 目前依舊是其它指令碼語言強勁的競爭對手,這主要歸功於其核心維護團隊的快速更新。

自從 PHP 7.0 釋出以來,社群見證了許多新特性的誕生,極大地改進了開發者在專案中應用 PHP 的方式。提高 PHP 應用的效能和安全性,是這些改進的主要目的。

PHP 最近實現了又一個里程碑 —— 釋出 PHP 7.3。新版本帶來了一些急需的更新。

在本文中,我將論述新推出的 PHP 7.3 特性 和更新。好訊息是,你可以在你的測試伺服器上自行安裝新版本、檢視新功能。但老生常談,切勿在生產伺服器上使用 RC 版本更新,可能會破壞你已經上線的應用。

以下是7.3版中引入的一些更新,與以前的版本相比,它們大大提高了 PHP 7.3 的效能 。

  • 靈活的 Heredoc 和 Nowdoc 語法
  • 函式呼叫時允許尾隨逗號
  • JSON_THROW_ON_ERROR
  • PCRE2 遷移
  • list() 分配參考
  • is_countable 函式
  • array_key_first(), array_key_last()
  • Argon2 密碼雜湊增強功能
  • 棄用和刪除 image2wbmp()
  • 棄用和刪除不區分大小寫的常量
  • 相同站點 Cookie
  • FPM 更新
  • 改進 Windows 下的檔案刪除

讓我們逐一討論上述的每一個更新。

靈活的 Heredoc 和 Nowdoc 語法

Heredoc 和 Nowdoc 語法能夠在使用多行長字串時起到很大幫助。它要求結束識別符號應當為出現在新行的首個字串。

// 除了這樣:

$query = <<<SQL

SELECT *

FROM `table`

WHERE `column` = true;

SQL;

// 這樣也可以:

$query = <<<SQL

   SELECT *

   FROM `table`

   WHERE `column` = true;

   SQL;
複製程式碼

總的來說,此更新提出了兩項改進,如下:

  1. 閉合識別符號前支援縮排
  2. 閉合識別符號後不再強制換行

在上面的例子裡,可以很容易地看出這些改動。

函式呼叫中允許尾部逗號

在引數、元素、變數列表結尾,追加尾部逗號。有時我們在陣列內以及函式呼叫(尤其是可變參函式)時需要傳遞大量元素,若是漏掉一個逗號,便會報錯。鑑於如上情況,尾部逗號便顯得十分有用。這個特性已經允許在陣列內使用,並且從 PHP 7.2 開始,分組名稱空間(Grouped Namespaces)語法也開始支援尾部逗號。

use Foo\Bar\{
   Foo,
   Bar,
};

$foo = [
   'foo',
   'bar',
];
複製程式碼

當新值需要被追加在此處時,尾部逗號便顯得十分實用。在可變參函式例如 unset() 內,更是如此。

unset(
   $foo,
   $bar,
   $baz,
);
複製程式碼

同時,當你使用 compact() 函式給模版引擎傳遞一批變數時,也是個能用到的例子。

echo $twig->render(
   'index.html',
   compact(
       'title',
       'body',
       'comments',
   )
);
複製程式碼

在某些需要構造連續或分組資料情況下,經常要使用 array_merge() 函式合併陣列。也可以利用尾部逗號:

$newArray = array_merge(
   $arrayOne,
   $arrayTwo,
   ['foo', 'bar'],
);
複製程式碼

同樣,你也可以在呼叫任意方法、函式以及閉包時使用此特性。

class Foo
{
 public function __construct(...$args) {
   //
 }

 public function bar(...$args) {
   //
 }

 public function __invoke(...$args) {
   //
 }
}

$foo = new Foo(
 'constructor',
 'bar',
);

$foo->bar(
 'method',
 'bar',
);

$foo(
 'invoke',
 'bar',
);
複製程式碼

JSON_THROW_ON_ERROR

解析 JSON 響應資料,有 json_encode() 以及 json_decode() 兩個函式可供使用。不幸的是,它們都沒有恰當的錯誤丟擲表現。json_encode 失敗時僅會返回 falsejson_decode 失敗時則會返回 null,而 null 可作為合法的 JSON 數值。唯一獲取錯誤的方法是,呼叫 json_last_error()json_last_error_msg(),它們將分別返回機器可讀和人類可讀的全域性錯誤狀態。

該 RFC 提出的解決方案是,為 JSON 函式新增 JSON_THROW_ON_ERROR 常量用於忽略全域性錯誤狀態。當錯誤發生時,JSON 函式將會丟擲 JsonException 異常,異常訊息(message)為 json_last_error() 的返回值,異常程式碼(code)為 json_last_error_msg() 的返回值。如下是呼叫例子:

json_encode($data, JSON_THROW_ON_ERROR);

json_decode("invalid json", null, 512, JSON_THROW_ON_ERROR);

// 丟擲 JsonException 異常
複製程式碼

升級 PCRE2

PHP 使用 PCRE 作為正規表示式引擎。但從 PHP 7.3 開始,PCRE2 將作為新的正則引擎大顯身手。所以,你需要將現有的正規表示式遷移到符合 PCRE2 的規則。這些規則比以前更具侵入性。請看以下例項:

preg_match('/[\w-.]+/', '');
複製程式碼

這個表示式在新版 PHP 內將會匹配失敗且不會觸發警告。因為 PCRE2 現嚴格要求,若需匹配連字元(-)而非用於表示範圍,則必須移動到末尾或將其轉義。

更新到 PCRE2 10.x 後,支援了以下以及更多特性:

  • 相對後向引用 \g{+2}(等效於已存在的 \g{-2}
  • PCRE2 版本檢查 (?(VERSION>=x)...)
  • (*NOTEMPTY)(*NOTEMPTY_ATSTART) 告知引擎勿返回空匹配
  • (*NO_JIT) 禁用 JIT 優化
  • (*LIMIT_HEAP=d) 限制堆大小為 d KB
  • (*LIMIT_DEPTH=d) 設定回溯深度限制為 d
  • (*LIMIT_MATCH=d) 設定匹配數量限制為 d

譯者注:國內正則術語參差不一,「後向引用」—— Back References,又稱「反向引用」、「回溯引用」等,此處參考 PHP 官方手冊的中文譯本。

list() 賦值引用

PHP 中的 list() 現在可以賦值給引用,在當前版本中 list() 中賦值不能使用引用,在 PHP 7.3 中將允許使用引用,新改進的語法如下:

$array = [1, 2];
list($a, &$b) = $array;
複製程式碼

相當於

$array = [1, 2];
$a = $array[0];
$b =& $array[1];
複製程式碼

在 PHP 7.3 的變更中,我們還可以與 foreach() 方法一起巢狀使用

$array = [[1, 2], [3, 4]];
foreach ($array as list(&$a, $b)) {
   $a = 7;
}
var_dump($array);
複製程式碼

is_countable 函式

在 PHP 7.2 中,用 count() 獲取物件和陣列的數量。如果物件不可數,PHP 會丟擲警告⚠️ 。所以需要檢查物件或者陣列是否可數。 PHP 7.3 提供新的函式 is_countable() 來解決這個問題。

該 RFC 提供新的函式 is_countable(),對陣列型別或者實現了 Countable 介面的例項的變數返回 true 。

之前:

if (is_array($foo) || $foo instanceof Countable) {
   // $foo 是可數的
}
複製程式碼

之後:

if (is_countable($foo)) {
   // $foo 是可數的
}
複製程式碼

array_key_first(), array_key_last()

當前版本的 PHP 允許使用 reset()end()key() 等方法,通過改變陣列的內部指標來獲取陣列首尾的鍵和值。現在,為了避免這種內部干擾,PHP 7.3 推出了新的函式來解決這個問題:

  • $key = array_key_first($array); 獲取陣列第一個元素的鍵名
  • $key = array_key_last($array); 獲取陣列最後一個元素的鍵名

讓我們看一個例子:

// 關聯陣列的用法
$array = ['a' => 1, 'b' => 2, 'c' => 3];

$firstKey = array_key_first($array);
$lastKey = array_key_last($array);

assert($firstKey === 'a');
assert($lastKey === 'c');

// 索引陣列的用法
$array = [1 => 'a', 2 => 'b', 3 => 'c'];

$firstKey = array_key_first($array);
$lastKey = array_key_last($array);

assert($firstKey === 1);
assert($lastKey === 3);
複製程式碼

譯者注:array_value_first()array_value_last() 並沒有通過 RFC 表決;因此 PHP 7.3 內僅提供了 array_key_first() 以及 array_key_last() 函式。 參考連結:wiki.php.net/rfc/array_k…

Argon2 和 Hash 密碼加密效能增強

在PHP的早期版本中,我們增加了Argon2和雜湊密碼加密演算法,這是一種使用雜湊加密演算法來保護密碼的現代演算法。它有三種不同的型別,Argon2i,Argon2d和Argon 2id。 我們針對Argon2i密碼雜湊和基於密碼的金鑰生成進行了優化。 Argon2d效能更快,並使用依賴於記憶體的資料訪問。 Argon2i使用與記憶體無關的資料訪問。 Argon2id是Argon2i和Argon2d的混合體,使用依賴於資料和與資料獨立的儲存器訪問的組合。

password_hash():

Argon2id現在是在paswword_ *函式中使用的推薦的Argon2變數。

具有自定義成員方法的名稱的Argon2id與PASSWORD_ARGON2I的使用方法相同
password_hash('password',PASSWORD_ARGON2ID,['memory_cost'=> 1 << 17,'time_cost'=> 4,'threads'=> 2]);
複製程式碼

password_verify();

除了Argon2i之外,password_verify()函式也適用於Argon2id。

password_needs_rehash();

此函式也將接受Argon2id雜湊值,如果任何變數成員發生變化,則返回true。

$hash = password_hash('password', PASSWORD_ARGON2ID);
password_needs_rehash($hash, PASSWORD_ARGON2ID); // 返回假
password_needs_rehash($hash, PASSWORD_ARGON2ID, ['memory_cost' => 1<<17]); // 返回真
複製程式碼

廢棄並移除 image2wbmp()

該函式能夠將影像輸出為 WBMP 格式。另一個名為 imagewbmp() 的函式也同樣具備單色轉換的作用。因此,出於重複原因,image2wbmp() 現已被廢棄,你可使用 imagewbmp() 代替它。此函式被棄用後,再次呼叫它將會觸發已棄用警告。待後續此函式被移除後,再次呼叫它將會觸發致命錯誤。

廢棄並移除大小寫不敏感的常量

使用先前版本的 PHP,你可以同時使用大小寫敏感和大小寫不敏感的常量。但大小寫不敏感的常量會在使用中造成一點麻煩。所以,為了解決這個問題,PHP 7.3 廢棄了大小寫不敏感的常量。

原先的情況是:

  • 類常量始終為「大小寫敏感」。
  • 使用 const 關鍵字定義的全域性常量始終為「大小寫敏感」。注意此處僅僅是常量自身的名稱,不包含名稱空間名的部分,PHP 的名稱空間始終為「大小寫不敏感」。
  • 使用 define() 函式定義的常量預設為「大小寫敏感」。
  • 使用 define() 函式並將第三個引數設為 true 定義的常量為「大小寫不敏感」。

如今 PHP 7.3 提議廢棄並移除以下用法:

  • In PHP 7.3: 廢棄使用 true 作為 define() 的第三個引數。
  • In PHP 7.3: 廢棄使用與定義時的大小寫不一致的名稱,訪問大小寫不敏感的常量。truefalse 以及 null 除外。

同站點 Cookie

PHP 7.3 在建議在使用 cookies 時,增加同站點標誌。這個 RFC 會影響4個系統函式。

  1. setcookie
  2. setrawcookie
  3. session_set_cookie_params
  4. session_get_cookie_params

這個影響會在兩種情況下起作用。其中一種方式會新增函式的新引數 ,另一種方式允許以陣列形式的選項代替其他單獨選項。

bool setcookie(

   string $name

   [, string $value = ""

   [, int $expire = 0

   [, string $path = ""

   [, string $domain = ""

   [, bool $secure = false

   [, bool $httponly = false ]]]]]]

)

bool setcookie (

   string $name

   [, string $value = ""

   [, int $expire = 0

   [, array $options ]]]

)

// 兩種方式均可.
複製程式碼

FPM 更新

FastCGI 程式管理器也進行了更新,現在提供了新的方式來記錄 FPM 日誌。

log_limit: 設定允許的日誌長度,可以超過 1024 字元。

log_buffering: 允許不需要額外緩衝去操作日誌。

decorate _workers_output: 當啟用了 catch_workers_output 時,系統會去禁用渲染輸出。

改進 Windows 下的檔案刪除

官方文件所述:

預設情況下,檔案描述符以共享讀、寫、刪除的方式去操作。 這很有效的去對映 POSIX 並允許去刪除正在使用中的檔案。但這並不是100%都是一樣的,不同的平臺可能仍存在一些差異。刪除操作之後,檔案目錄仍存在直到所有的檔案操作被關閉。

結束語

之前我們已經講解了最新版本的 PHP7.3 的特點,包含了許多新增跟棄用的功能。這些功能都可以在 php.net 網站上找到,並且已經合併到主分支上了。你現在就可以使用這些新功能部署在自己的伺服器上,你也可以開啟官方RFC頁面查閱每一個詳細版本。如果你對著新版 PHP7.3 有任何問題,你可以在評論下寫下自己的想法。 如果你喜歡這篇文章,並且覺得它很有幫助,你可以在 twitter 上關注我,來獲得更多的資訊!

文章轉自:learnku.com/php/t/21549
更多文章:learnku.com/laravel/c/t…

相關文章