目錄

PHP 8 正式釋出

千呼萬喚始出來!PHP 8.0 正式釋出!

今天七月的 LaravelConf Taiwan 2020 很榮幸成為開場講者,並且跟大家介紹 PHP 8 的新特性,事隔近半年後,總算推出了正式版本。(簡報參考)當時為了研究 JIT 原理,還跑去看組合語言,都覺得人生掉到谷底了,最後還是單純說明 JIT 流程和新特性為主。

以下再重新介紹幾個我覺得有趣的新特性,除了之前簡報有講的外,也有這半年後來被納入實作的。

官方例子非常經典:

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

為了要特別給第四個參數是 false,則必須要把中間預設的參數都打上一次才能正常運作。

htmlspecialchars($string, double_encode: false);

有了 Named arguments 後,只要指定欄位名稱,即可傳入對應的值,而其他參數都會使用預設值。

類似的問題我也很常遇到,比方說 http_build_query()enc_type: PHP_QUERY_RFC3986json_decode()flags: JSON_THROW_ON_ERROR 等,用這個寫法就能清楚且方便地呼叫函式了。

但這功能也是雙面刃,因為參數可以不按順序方便地呼叫,這樣就有可能被當成 array 使用,並不斷的新增,最後這個 function 就會違反單一職責原則了。

Named arguments 詳情可參考 RFC

這是一個很像 switch 語法的新語法:

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

我個人認為這兩個語法最大的差異在於,match 比對到之後的行為,只能接受一行,但 switch 可以多行。這個關鍵差異將會影響到 switch 因為可以做很多事,所以很容易看到 switchswitchif else,這也是違反了單一職責原則。但 match 呢?它辦不到這點,使用它就必須 extract method。

Match expression 詳情可參考 RFC

很多語言支援的寫法:

$country =  null;

if ($session !== null) {
  $user = $session->user;

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

這個寫法看起來很方便,但我目前想到的問題是,如果寫了一長串,就很有可能不知道在哪裡回 null。在資料處理上比較沒有問題,像 Laravel config('session.user.address.country') 若中間有個設定沒有,也是會直接回傳 null;程式執行流程上也許會怪怪的,比方說:

$country = $this->getUserService()?->getUser('foo')?->getAddress()?->country;

這個寫法下,如果回 null 就會有需要知道是哪一段回的,因為取 service 物件或取 user 物件失敗是兩個不同例外情境。

Nullsafe operator 詳情可參考 RFC