PHP Conference Japan 2024

assert

(PHP 4, PHP 5, PHP 7, PHP 8)

assert檢查斷言

描述

assert(混合 $assertion, Throwable|字串|null $description = null): 布林值

assert() 允許定義預期:斷言在開發和測試環境中生效,但在正式環境中會被優化掉,使其零成本。

斷言應僅用作除錯功能。它們的一個用例是作為前置條件的完整性檢查,這些前置條件應始終為 true,如果它們未被維持,則表示存在一些程式錯誤。另一個用例是確保存在某些功能,例如擴充函式或某些系統限制和功能。

由於斷言可以設定為被消除,因此它們 *不應* 用於正常的運行時操作,例如輸入參數檢查。根據經驗,即使停用斷言檢查,程式碼也應按預期運行。

assert() 將檢查 assertion 中給出的預期是否成立。如果不成立,因此結果為 false,它將根據 assert() 的設定方式採取相應的操作。

assert() 的行為由以下 INI 設定決定

斷言設定選項
名稱 預設值 描述 更新日誌
zend.assertions 1
  • 1:產生並執行程式碼(開發模式)
  • 0:產生程式碼,但在運行時跳過它
  • -1:不產生程式碼(正式環境模式)
 
assert.active true 如果為 falseassert() 不會檢查預期,並無條件返回 true 自 PHP 8.3.0 起已棄用。
assert.callback null

當斷言失敗時要呼叫的使用者定義函式。其簽章應為

assert_callback(
    string $file,
    int $line,
    null $assertion,
    string $description = ?
): void

在 PHP 8.0.0 之前,回呼函式的簽章應為

assert_callback(
    string $file,
    int $line,
    string $assertion,
    string $description = ?
): void

自 PHP 8.3.0 起已棄用。
assert.exception true 如果為 true,如果預期未被維持,則會拋出 AssertionError 自 PHP 8.3.0 起已棄用。
assert.bail false 如果為 true,如果預期未被維持,則會中止 PHP 腳本的執行。 自 PHP 8.3.0 起已棄用。
assert.warning true 如果為 true,如果預期未被維持,則會發出 E_WARNING。如果啟用了 assert.exception,則此 INI 設定無效。 自 PHP 8.3.0 起已棄用。

參數

assertion

這是任何返回一個值的表達式,它將被執行,其結果用於指示斷言是成功還是失敗。

警告

在 PHP 8.0.0 之前,如果 assertionstring 型態,它會被解釋為 PHP 程式碼並透過 eval() 執行。此字串將作為第三個參數傳遞給回呼函式。此行為在 PHP 7.2.0 中已 *棄用*,並在 PHP 8.0.0 中已 *移除*。

description

如果 descriptionThrowable 的實例,則僅在 assertion 執行並失敗時才會拋出它。

注意事項:

從 PHP 8.0.0 開始,這會在呼叫可能已定義的 assertion 回呼 *之前* 完成。

注意事項:

從 PHP 8.0.0 開始,無論 assert.exception 的設定為何,物件 都會被拋出。

注意事項:

從 PHP 8.0.0 開始,assert.bail 設定在此情況下無效。

如果 description 是一個 字串,則當發出例外或警告時,將會使用此訊息。這是一個可選的描述,如果 assertion 失敗,它將會包含在錯誤訊息中。

如果省略 description,則會在編譯時建立一個預設描述,其內容等同於呼叫 assert() 的原始碼。

返回值

如果至少滿足以下其中一個條件,assert() 將始終返回 true

  • zend.assertions=0
  • zend.assertions=-1
  • assert.exception=1
  • assert.bail=1
  • 自訂的例外物件被傳遞給 description

如果不滿足任何條件,如果 assertion 為真值,assert() 將返回 true,否則返回 false

更新日誌

版本 描述
8.3.0 所有 assert. INI 設定都已被棄用。
8.0.0 assert() 將不再評估字串引數,而是將它們視為任何其他引數。應使用 assert($a == $b) 而不是 assert('$a == $b')php.ini 指令 assert.quiet_eval 和常數 ASSERT_QUIET_EVAL 也已被移除,因為它們不再有任何作用。
8.0.0 如果 descriptionThrowable 的實例,則當 assertion 失敗時,無論 assert.exception 的值為何,都會拋出該物件。
8.0.0 如果 descriptionThrowable 的實例,則即使設定了使用者回呼,也不會呼叫它。
8.0.0 在命名空間內宣告名為 assert() 的函式已不再允許,並且會產生 E_COMPILE_ERROR 錯誤。
7.3.0 在命名空間內宣告名為 assert() 的函式已被棄用。現在,此類宣告會發出 E_DEPRECATED 警告。
7.2.0 使用 字串 作為 assertion 已被棄用。現在,當 assert.activezend.assertions 都設定為 1 時,它會發出 E_DEPRECATED 通知。

範例

範例 #1 assert() 範例

<?php
assert
(1 > 2);
echo
'Hi!';

如果啟用了 assertion (zend.assertions=1),上述範例將輸出

Fatal error: Uncaught AssertionError: assert(1 > 2) in example.php:2
Stack trace:
#0 example.php(2): assert(false, 'assert(1 > 2)')
#1 {main}
  thrown in example.php on line 2

如果停用了 assertion (zend.assertions=0zend.assertions=-1),上述範例將輸出

Hi!

範例 #2 使用自訂訊息

<?php
assert
(1 > 2, "Expected one to be greater than two");
echo
'Hi!';

如果啟用了斷言,以上範例將會輸出

Fatal error: Uncaught AssertionError: Expected one to be greater than two in example.php:2
Stack trace:
#0 example.php(2): assert(false, 'Expected one to...')
#1 {main}
  thrown in example.php on line 2

如果停用了斷言,以上範例將會輸出

Hi!

範例 #3 使用自訂的例外類別

<?php
class ArithmeticAssertionError extends AssertionError {}

assert(1 > 2, new ArithmeticAssertionError("Expected one to be greater than two"));
echo
'Hi!';

如果啟用了斷言,以上範例將會輸出

Fatal error: Uncaught ArithmeticAssertionError: Expected one to be greater than two in example.php:4
Stack trace:
#0 {main}
  thrown in example.php on line 4

如果停用了斷言,以上範例將會輸出

Hi!

參見

新增註解

使用者貢獻的註解 2 則註解

hodgman at ali dot com dot au
16 年前
如同維基百科所述 - 「斷言主要是一種開發工具,當程式發佈給大眾時,它們通常會被停用。」 以及「斷言應該用於記錄邏輯上不可能的情況並發現程式錯誤—— 如果發生了『不可能』的情況,那麼顯然有什麼根本性的錯誤。這與錯誤處理不同:大多數錯誤情況都是有可能發生的,儘管有些在實務中極不可能發生。使用斷言作為通用的錯誤處理機制通常是不明智的:斷言不允許從錯誤中優雅地恢復,而且斷言失敗通常會突然中止程式的執行。斷言也不會顯示使用者友善的錯誤訊息。」

這意味著「gk at proliberty dot com」提出的強制啟用斷言的建議,即使它們已被手動停用,也違反了僅將它們用作開發工具的最佳實務。
sven at rtbg dot de
9 個月前
隨著 PHP 8.3 中所做的最新更改(棄用影響斷言的 INI 設定),以及越來越多的開放原始碼函式庫利用 `assert()` 作為確保 PHP 核心函式呼叫的模糊回傳案例實際上未被觸發的簡單方法(例如,沒有回傳 NULL 或 FALSE,而是回傳有用的值),關於斷言僅作為開發期間使用的工具的評論應被視為無效。

此外,靜態程式碼分析工具使用從 `assert($x instanceof MyClass)` 獲得的知識來了解可能的類型。

斷言正在生產程式碼中積極使用,它們很有用,停用它們只會獲得最小的效能提升,因為斷言的表達式通常非常小。

在適用的情況下使用此工具!
To Top