PHP 中的斷言經常使用於調試,檢查一個表達式或語句是否爲 FALSE。本文帶你從新認識 PHPassert()
函數的神(Qi)通(Yin)廣(Ji)大(Qiao)。本文基於 PHP Version 7.1.28php
編寫程序時,常會作出必定的假設,那斷言就是用來捕獲假設的異常,咱們也能夠認爲斷言是異常的一種特殊形式。express
斷言通常用於程序執行結構的判斷,不可以讓斷言處理業務流程。用的最多的場景就是單元測試,通常的單元測試框架都採用了斷言。segmentfault
assert(1 == 2); // 運行結果: // Warning: assert(): assert(1 == 2) failed in /Users/shocker/Desktop/demo.php on line 25
在 PHP 中,採用 assert() 函數對錶達式進行斷言。安全
// PHP 5 assert ( mixed $assertion [, string $description ] ) : bool // PHP 7 assert ( mixed $assertion [, Throwable $exception ] ) : bool
參數 assertion 既支持表達式,也支持表達式字符串(某些特定的場景會用到,好比判斷某個字符串表達式是否合法)
若是 assertion 是字符串,它將會被 assert()
當作 PHP 代碼來執行。assertion 是字符串的優點是當禁用斷言時它的開銷會更小,而且在斷言失敗時消息會包含 assertion 表達式。框架
斷言這個功能應該只被用來調試。你應該用於完整性檢查時測試條件是否始終應該爲 TRUE,來指示某些程序錯誤,或者檢查具體功能的存在(相似擴展函數或特定的系統限制和功能)。函數
斷言不該該用於普通運行時操做,相似輸入參數的檢查。做爲一個經驗法則,在斷言禁用時你的代碼也應該可以正確地運行。post
使用示例:單元測試
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 配置。ui
另外,還支持經過 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()
函數設置,效果同樣
標誌 | INI 設置 | 默認值 | 描述 |
---|---|---|---|
ASSERT_ACTIVE | assert.active | "1" | 啓用 assert() 斷言 |
ASSERT_WARNING | assert.warning | "1" | 爲每一個失敗的斷言產生一個 PHP 警告(warning) |
ASSERT_BAIL | assert.bail | "0" | 在斷言失敗時停止執行 |
ASSERT_QUIET_EVAL | assert.quiet_eval | "0" | 在斷言表達式求值時禁用 error_reporting |
ASSERT_CALLBACK | assert.callback | NULL | 斷言失敗時調用該回調函數 |
ASSERT_EXCEPTION | assert.exception | "0" | 在斷言失敗時產生 AssertionError 異常 (自 PHP 7.0.0 起有效) |
zend.assertions
是個特殊的配置(PHP >= 7.0.0 支持),控制不一樣運行環境下斷言的行爲,僅可用 ini_set()
進行設置。而且,設置了1
就不能再設置爲-1
,反之亦然,其餘不受限。
- 1: 編譯代碼,並執行(開發模式)
- 0: 編輯代碼,但運行時跳過
- -1: 不編譯代碼(生產模式)
zend.assertions
、assert.exception
相關配置及其特性PHP >= 7.2 版本開始,參數 assertion 再也不支持字符串
詳見 PHP 7.2.x 中廢棄的功能
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() 測試不經過:');
是否是跟咱們用 PHPUnit 寫單元測試很像😆
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 開始廢棄支持字符串表達式的緣由。
感謝您的閱讀,以爲內容不錯,點個贊吧 😆
原文地址: https://shockerli.net/post/php-assert/