首頁  >  文章  >  後端開發  >  什麼是PHP斷言(assert)?該如何使用?

什麼是PHP斷言(assert)?該如何使用?

王林
王林轉載
2019-08-29 15:46:257941瀏覽

PHP 中的斷言常用於偵錯,檢查一個表達式或語句是否為 FALSE。本文帶你重新認識 PHP assert() 函數的神通廣大。

本文基於PHP Version 7.1.28

一、什麼是斷言

編寫程式時,常會做出一定的假設,那斷言就是用來捕捉假設的異常,我們也可以認為斷言是異常的一種特殊形式。

斷言一般用於程式執行結構的判斷,不可讓斷言處理業務流程。用的最多的場景就是單元測試,一般的單元測試框架都採用了斷言。

assert(1 == 2);
// 运行结果:
// Warning: assert(): assert(1 == 2) failed in /Users/shocker/Desktop/demo.php on line 25

二、PHP中的斷言

在 PHP 中,採用 assert()函數對表達式進行斷言。

// PHP 5assert ( mixed $assertion [, string $description ] ) : bool
// PHP 7assert ( mixed $assertion [, Throwable $exception ] ) : bool

四、傳統的斷言方式

#參數assertion 既支援表達式,也支援表達式字串(某些特定的場景會用到,例如判斷某個字串表達式是否合法)

如果assertion 是字串,它將會被 assert() 當做PHP 程式碼來執行。 assertion 是字串的優點是當停用斷言時它的開銷會更小,並且在斷言失敗時訊息會包含 assertion 表達式。

斷言這個功能應該只會被用來除錯。你應該用於完整性檢查時測試條件是否始終應該為 TRUE,來指示某些程式錯誤,或檢查特定功能的存在(類似擴充函數或特定的系統限制和功能)。

斷言不應該用於普通運行時操作,類似輸入參數的檢查。作為一個經驗法則,在斷言禁用時你的程式碼也應該能夠正確地運行。

實例:

function my_assert_handler($file, $line, $code, $desc){    echo "Assertion Failed:
    File '{$file}'
    Line '{$line}'
    Code '{$code}'
    Desc '{$desc}'
";
}
// 设置回调函数
assert_options(ASSERT_CALLBACK, 'my_assert_handler');
// 让一则断言失败
assert('1 == 2', '1 不可能等于 2');

執行結果:

Assertion Failed:
    File '/Users/shocker/Desktop/demo.php'
    Line '29'
    Code '1 == 2'
    Desc '1 不可能等于 2'

#五、支援異常的斷言

在PHP 7 中,assert() 是一種語言結構,允許在不同環境中生效不同的措施,具體可見 zend.assertions配置。

另外,也支援透過 AssertionError 捕捉錯誤。

使用範例:

assert_options(ASSERT_EXCEPTION, 1); 
// 在断言失败时产生异常
try {    
// 用 AssertionError 异常替代普通字符串
    assert(true == false, new AssertionError('True is not false!'));
} catch (Throwable $e) {    
echo $e->getMessage();
}

運行結果:

True is not false!

#六、對斷言行為控制

PHP 支援 assert_options()函數對斷言進行配置,也可用ini 進行設定

以下配置中,常數標誌用於 assert_options() 函數進行配置,ini 設定用於 ini_set() 函數設置,效果一樣

什麼是PHP斷言(assert)?該如何使用?

#zend.assertions 是特殊的設定(PHP >= 7.0.0 支援),控制不同運作環境下斷言的行為,只可用 ini_set() 設定。並且,設定了1就不能再設定為-1,反之亦然,其他不受限。

1: 編譯程式碼,並執行(開發模式)

0: 編輯程式碼,但執行時間跳過

-1: 不編譯程式碼(生產模式)

七、版本的不相容

PHP >= 5.4.8,description 可作為第四個參數提供給ASSERT_CALLBACK 模式裡的回呼函數

在PHP 5 中,參數assertion 必須是可執行的字串,或是執行結果為布林值的表達式

在PHP 7 中,參數assertion 可以是任意表達式,並用其運算結果作為斷言的依據

在PHP 7 中,參數exception 可以是個 Throwable 對象,用於捕獲表達式運行錯誤或斷言結果為失敗。 (當然 assert.exception 需開啟)

PHP >= 7.0.0,支援 zend.assertions、assert.exception 相關設定及其特性

PHP >= 7.2 版本開始,參數assertion 不再支援字串

Deprecated: assert(): Calling assert() with a string argument is deprecated

八、應用程式場景

#偵錯輸出:

#先看範例:

assert('1 == 2', '1 不可能等于 2');

運行結果:

Warning: assert(): 1 不可能等于 2: "1 == 2" failed in /Users/shocker/Desktop/demo.php on line 10

類似於:

$expression = 1 == 2;
if (!($expression)) {
    echo "1 不可能等于 2\n";
    var_dump($expression);
    echo __FILE__ . "\n";
}

但是,我們無法得知$expression 的具體表達式,也無法得知具體的執行行數。

九、單元測試

function arraySum(array $nums) {
    $sum = 0;    foreach ($nums as $n) {
        $sum += $n;
    }    return $sum;
}

assert(arraySum([1, 2, 3]) == 6, 'arraySum() 测试不通过:');
assert(is_numeric(arraySum([1, 2, 3])), 'arraySum() 测试不通过:');

#第十、驗證表達式

Tip:

PHP 7 開始,新增了 Error 類別用於捕捉PHP 內建錯誤,包括語法錯誤。 Error 與先前的 Exception 都繼承自 Throwable,所以從 7.0.0 開始,Throwable 可以捕捉一切錯誤和異常。

下例示範如何驗證某個字串表達式是否為合法的PHP 表達式:

try {
    assert('a +== 1');
} catch (Throwable $e) {    
    echo $e->getMessage(), "\n";
}

運行結果:

Failure evaluating code: 
a +== 1

##十一、安全性問題

假如是下列程式碼會有什麼結果呢?

function demo(){
    file_put_contents('data.log', 'shockerli.net');
    return true;
}

$func = $_GET["func"];
assert("$func()");

所以,对于 assert 函数,正常情况下是不建议用于生产环境的。

与 eval 一样会执行任何 PHP 代码,危害极大。这也是 PHP 从 7.2 开始废弃支持字符串表达式的原因

感谢您的阅读,如有错误请指出。

相了解更多相关问题请访问PHP中文网:PHP视频教程

以上是什麼是PHP斷言(assert)?該如何使用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除