PHP 8.5正式釋出:全面解析管道運算子、高階URI解析及記憶體管控等十大核心升級

PHP 8.5正式釋出:全面解析管道運算子、高階URI解析及記憶體管控等十大核心升級

文章目录

  • PHP 8.5中的新功能和改進
  • 使用管道運算子連結函式呼叫
  • 使用新的URI擴充套件解析URL
  • 使用新的max_memory_limit INI指令嚴格控制記憶體
  • 獲取陣列中的第一個或最後一個值
  • 提醒您使用函式的返回值
  • PHP 8.5中的棄用和移除
  • 小結

PHP 8.5正式釋出

PHP 團隊釋出了開源指令碼語言 PHP 8.5 版本,該語言為包括使用 WordPress CMS 的網站在內的眾多 Web 應用提供支援。

PHP 8.5 於 11 月釋出,標誌著 PHP 社羣承諾每年釋出重大更新的第二年,並且每個版本都將獲得兩年的積極支援

雖然 8.5 是全新的版本,但我們已在年度 PHP 基準測試中對其進行了全面評估,測試涵蓋了各種流行的 CMS 平臺和框架。

如果您計劃將 PHP 應用程式遷移到 8.5 版本,則需要了解此最新版本中的更改。這包括您可以利用的新功能(可用於改進程式碼)以及 PHP 開發人員即將移除的舊功能。

以下是我們認為新版本的主要亮點:

PHP 8.5中的新功能和改進

讓我們從 PHP 程式碼庫的新增內容開始。這些變更通常以徵求意見稿 (RFC) 的形式出現,最終可能會獲得批准並納入未來的 PHP 版本。

以下介紹的新功能是 PHP 8.5 版本中最受關注的幾個方面。

使用管道運算子連結函式呼叫

新的管道運算子 (|>) 以一種 JavaScript 程式設計師會感到似曾相識的方式連結函式呼叫。管道從左到右執行,每一步都傳遞一個值。

在之前的 PHP 版本中,程式設計師可能需要透過巢狀函式或逐個執行函式呼叫並檢查每一步的返回值來完成類似的任務。

以下是一個使用新管道運算子的簡單示例:

$text = ' New-in-php-8.4 ';
$result = $text
|> trim(...)
|> (fn($str) => str_replace('4', '5', $str))
|> (fn($str) => str_replace('-', ' ', $str))
|> strtoupper(...);
var_dump($result);
// string(14) "NEW IN PHP 8.5"

(請注意,我們使用的是 PHP 8.1 中引入的一等可呼叫語法 (...),該語法用於呼叫 trim()strtoupper() 函式。)

上面的管道鏈可以寫在一行中,但可讀性正是這個新運算子的優勢之一。

上述操作等價於將這些操作(按相反順序)巢狀在一起,如下所示:

$text = " New-in-php-8.4 ";
$result = strtoupper(
str_replace(‘-, ' ',
str_replace('4', '5', 
trim($text)
)
)
);

或者,程式設計師可能在早期的 PHP 版本中像這樣完成這項任務:

$text = " New-in-php-8.4 ";
$result = trim($text);
$result = str_replace('4', '5', $result);
$result = str_replace(‘-, ' ', $result);
$result = strtoupper($result);

使用新的URI擴充套件解析URL

URL(也稱為 URI,更嚴謹的說法)是 Web 導航的關鍵,但 PHP 4 版本以來內建的 parse_url() 函式在處理格式錯誤的輸入時存在問題,這可能導致在嘗試操作或驗證網站地址時出現錯誤。

為了改進 URL 解析,PHP 8.5 引入了 uriparserLexbor 庫,分別支援 RFC 3986WHATWG URL 標準。

您可以透過以下方式使用新的 URI 擴充套件來呼叫 `uriparser` 庫:

$uri = new Uri\Rfc3986\Uri("https://www.dianavpn.com/blog/what-is-a-vpn/"); 
echo $uri->getScheme();       // https
echo $uri->getHost();         // www.dianavpn.com
echo $uri->getPath();         // /blog/what-is-a-vpn

或者,您可以選擇 Lexbor WHATWG URL 庫,如下所示:

$uri = new Uri\WagWg\Url("https://www.dianavpn.com/blog/what-is-a-vpn/"); 
echo $uri->getScheme();       // https
echo $uri->getUnicodeHost();  // www.dianavpn.com
echo $uri->getAsciiHost();    // www.dianavpn.com
echo $uri->getPath();         // /blog/what-is-a-vpn

以上示例最為基礎。PHP 8.5 中 URI 擴充套件所代表的兩個庫功能相同,但也存在顯著差異。

一個重要的區別是,RFC 3986 庫同時支援 URI 的“原始”和“規範化解碼”表示形式。這在處理百分比編碼的輸入和輸出時非常有用。例如,在瀏覽器中,以下兩個 URI 完全相同:

在之前的 PHP 版本中,您可能需要使用 rawurldecode()rawurllencode() 函式(它們也符合 RFC 3986 標準),但新的擴充套件程式開箱即用,可以處理 URI 的所有組成部分,無論它們是否經過編碼。

以下是一些直接摘自新解析 API 背後的 RFC 文件的示例:

$uri = new Uri\Rfc3986\Uri("https://%61pple:p%61ss@ex%61mple.com/foob%61r?%61bc=%61bc");
echo $uri->getRawUserInfo();  // %61pple:p%61ss
echo $uri->getUserInfo();     // apple:pass
echo $uri->getRawUsername();  // %61pple
echo $uri->getUsername();     // apple
echo $uri->getRawPassword();  // p%61ss
echo $uri->getPassword();     // pass
echo $uri->getRawHost();      // ex%61mple.com
echo $uri->getHost();         // example.com
echo $uri->getRawPath();      // /foob%61r
echo $uri->getPath();         // /foobar
echo $uri->getRawQuery();     // %61bc=%61bc
echo $uri->getQuery();        // abc=abc

使用帶有新擴充套件的 WHATWG URL 庫時,所有 URI 都被視為“原始”URI,因此沒有單獨的函式集來支援其他格式。但該庫可以在 URI 中常見的 ASCII 和 Unicode 字元之間進行轉換。

使用新的max_memory_limit INI指令嚴格控制記憶體

人們常說,能力越大,責任越大。如果這種權力包括選擇 PHP 應用程式可以使用的伺服器記憶體量,那麼當程序消耗的記憶體超過可用記憶體時,應用程式崩潰就可能需要您承擔責任。

典型的 PHP 安裝包含一個 php.ini 檔案,其中包含配置資訊,其中包括一個指令,用於指定任何 PHP 程序(或執行緒)的記憶體消耗限制。一個常見的 128 MB 記憶體限制的 INI 指令如下所示:

// php.ini
memory_limit 128M

在某些託管平臺上,PHP 應用程式的開發人員可以使用程式碼中的 ini_set() 函式動態地覆蓋 memory_limit

ini_set(‘memory_limit’, ‘256M’);
// Start code that requires up to 256 MB of memory

您還可以向函式傳遞值 -1,例如 ini_set('memory_limit', '-1'),以完全取消記憶體限制。

對於不熟悉應用程式執行伺服器記憶體配置的開發人員來說,覆蓋 INI 指令的記憶體限制可能存在風險。如果一個或多個 PHP 執行緒嘗試消耗超過總記憶體池的記憶體,則可能導致應用程式在執行時崩潰且不會發出警告。

PHP 8.5 新增了 max_memory_limit INI 指令,即使在開發人員可以使用 init_set() 函式調整程式碼記憶體使用的情況下,該指令也起到了硬性限制的作用。

以下是 PHP 8.5 安裝的 php.ini 檔案中的示例條目:

// php.ini
max_memory_limit 256M
memory_limit 128M

max_memory_limit 設定為 256 MB 時,我們的 PHP 程式碼會執行以下操作:

ini_set('memory_limit', '256M');  // This is OK
ini_set('memory_limit', '512M');  // Fail with warning
ini_set('memory_limit', '-1');    // Fail with warning

嘗試將記憶體限制設定為 512 MB(或無限制)以上值將不會成功。PHP 會將記憶體限制設定為 php.ini 檔案中 max_memory_limit 的值,併發出警告。(警告資訊可能會顯示在螢幕上並被記錄,具體取決於 PHP 安裝的錯誤報告設定。)

對於 PHP 8.5 開發人員來說,明智的做法是使用 ini_get() 函式來檢視是否已定義新的最大限制,例如 ini_get('max_memory_limit'),然後根據返回值進行調整。對於 8.5 之前的 PHP 版本,該呼叫會安全地返回 false

獲取陣列中的第一個或最後一個值

如果你之前認為 PHP 已經提供了讀取陣列中第一個或最後一個元素的值的函式,請舉手。

事實上,它並沒有。但從 PHP 7.3 開始,它提供了獲取陣列中第一個和最後一個的函式。因此,要查詢第一個和最後一個值,你可以使用 array_key_first()array_key_last() 函式,然後使用返回的鍵來引用你要查詢的值:

$array = ["One", "Two", "Three"];
echo $array[array_key_first($array)]; // "One"

PHP 8.5 簡化了這一步驟,允許您使用新的 array_first()array_last() 函式直接獲取陣列中的值。

一切都很簡單:

$array = ["One", "Two", "Three"];
echo array_first($array);  // "One"
echo array_last($array);   // "Three"
echo array_last([]);       // null

如上所示,空陣列會返回 null,但這本身並不能確認整個陣列為空,因為陣列中的某個值可能為null:

echo array_last([1, 2, null]); // null

提醒您使用函式的返回值

PHP 5.8 新增了一個 #[\NoDiscard] 屬性,用於指示函式的返回值可能至關重要。PHP 會檢查返回值是否被以某種方式使用,如果沒有,則會觸發警告。

一個簡單的例子:

#[\NoDiscard("this message property will be appended to the built-in warning.")]
function foo(): string {
return 'bar';
}
// Warning:
// The return value of function foo() is expected to be consumed,
// this message property will be appended to the built-in warning.
foo();
// This will not trigger a warning:
$result = foo();
// Also satisfactory is the (void) cast:
(void) foo();

在上面的示例中,定義函式的返回值在第一次執行時完全沒有被使用,從而觸發了警告。但是,當將其賦值給變數 $result 或強制轉換為 void 型別時,該值被認為已被使用。

PHP 8.5 中新增的這項功能對應的 RFC 文件的作者們描述了比上述簡單示例更具說服力的用法。其中一個場景是關鍵函式,其錯誤報告比簡單的透過/失敗更復雜,而透過函式的返回值來傳達錯誤資訊是最佳方式。

其他與屬性相關的增強功能

除了新增的 #[\NoDiscard] 屬性之外,新版本中對屬性後設資料功能的其他增強功能還包括:

  • 屬性現在可以指向常量。
  • #[\Override] 屬性現在可以應用於屬性。
  • #[\Deprecated] 屬性可以用於特性和常量。
  • 可以使用新的 #[\DelayedTargetValidation] 屬性來抑制在無效目標上使用的核心和擴充套件屬性的編譯時錯誤。

PHP 8.5中的棄用和移除

每個 PHP 版本釋出時都會列出一些功能,這些功能將被標記為在未來的版本中移除。在程式碼中使用已棄用的功能會觸發警告。當這些功能最終從 PHP 中移除時,繼續使用可能會導致致命錯誤。

以下是 PHP 8.5 中一些值得注意的已棄用或移除的功能:

  • 反引號運算子作為 shell_exec() 的別名已被棄用。
  • 非規範型別轉換名稱 (boolean)(integer)(double)(binary) 已被棄用。請改用 (bool)(int)(float)(string)
  • disable_classes INI 設定已被移除,因為它會導致各種引擎假設被破壞。
  • 使用分號而不是冒號結束 case 語句已被棄用。
  • 現在已棄用將 null 用作陣列偏移量或在呼叫 array_key_exists() 時使用 null。請改用空字串。
  • 現在不能再在 class_alias() 中使用 arraycallable 作為類別名。
  • __sleep()__wakeup() 魔術方法已被軟棄用。請改用 __serialize()__unserialize() 魔術方法。
  • 現在將 NaN 強制轉換為其他型別時會發出警告。
  • 現在使用 []list() 解構非陣列值(null 除外)時會發出警告。
  • 現在將浮點數(或看起來像浮點數的字串)強制轉換為 int 型別時,如果它們不能表示為 int ,則會發出警告。

小結

以上是 PHP 8.5 版本的主要更新內容。我們相信新的管道運算子和改進的 URI 解析功能將受到開發者的歡迎。或許連新的 array_first()array_last() 函式也包含在內,我們原本以為它們早就存在了。

但任何新的 PHP 版本都包含數百項更改。您可以在 PHP 官方 GitHub 程式碼庫中找到 PHP 8.5 更新的完整列表

評論留言