PHP中的断言通常用于调试,检查表达式或语句是否为FALSE。本文带你重新认识PHPassert()函数的神(气)通(印)光(济)达(巧)。本文基于PHPVersion7.1.28什么是断言?编写程序时,通常会做出某些假设。断言用于捕获假定的异常。我们也可以认为断言是异常的一种特殊形式。断言一般用于判断程序执行结构,断言不能用于处理业务流程。使用最多的场景是单元测试,一般的单元测试框架都使用断言。assert(1==2);//运行结果//Warning:assert():assert(1==2)failedin/Users/shocker/Desktop/demo.phponline25PHP中的断言在PHP中,使用assert()函数断言表达式。//PHP5assert(mixed$assertion[,string$description]):bool//PHP7assert(mixed$assertion[,Throwable$exception]):bool传统的断言方法(PHP5&7)参数断言支持表达式,和还支持表达式字符串(用于一些特定场景,比如判断某个字符串表达式是否合法)。如果assertion是一个字符串,它将被assert()作为PHP代码执行。断言是一个字符串的好处是当断言被禁用时它会更便宜,并且当断言失败时消息将包含断言表达式。断言此功能只应用于调试。您应该使用健全性检查来测试条件是否应始终为TRUE,以指示某些程序错误,或检查是否存在特定功能(如扩展功能或特定系统限制和功能)。断言不应用于正常的运行时操作,例如检查输入参数。根据经验,您的代码应该在禁用断言的情况下正确运行。用法示例:functionmy_assert_handler($file,$line,$code,$desc){echo"AssertionFailed:File'{$file}'Line'{$line}'Code'{$code}'Desc'{$desc}'";}//设置回调函数assert_options(ASSERT_CALLBACK,'my_assert_handler');//让断言失败assert('1==2','1cannotbeequalto2');运行结果:AssertionFailed:File'/Users/shocker/Desktop/demo.php'Line'29'Code'1==2'Desc'1cannotpossiblybeequalto2'支持异常断言(仅限PHP7)InPHP7、assert()是一种语言结构,可以让不同的措施在不同的环境下生效,详见zend.assertions配置。此外,还支持通过AssertionError捕获错误。用法示例:assert_options(ASSERT_EXCEPTION,1);//断言失败时产生一个异常$e->getMessage();}运行结果:真不假!控制断言行为PHP支持assert_options()函数来配置断言,也可以通过ini来设置下面的配置,constantflag用于assert_options()函数来配置,ini设置用于ini_set()函数设置,效果同标志INI设置默认值说明ASSERT_ACTIVEAssert.active"1"启用assert()assertionASSERT_WARNINGAssert.warning"1"foreachfailureassertiongeneratesaPHPwarning(warning)ASSERT_BAILassert.bail"0"abortsexecutiononassertionfailureASSERT_QUIET_EVALassert.quiet_eval"0"禁用error_reportingASSERT_CALLBACKassert.callbackNULL断言失败时的回调函数ASSERT_EXCEPTIONassert.exception"0"断言失败时产生AssertionError异常(PHP7.0.0起生效)zend.assertions是一个特殊的配置(PHP支持>=7.0.0),控制断言在不同运行环境下的行为,只能设置与ini_set()。而且,如果设置为1,则不能设置为-1,反之亦然,其他不限。1:编译代码并执行(开发模式)0:编辑代码,但跳过运行时对于ASSERT_CALLBACK模式下的回调函数在PHP5中,参数断言必须是一个可执行的字符串,或者是一个运算结果为布尔值的表达式在PHP7,参数assertion可以是任意表达式,并以其运行结果作为断言Basis在PHP7中,参数exception可以是Throwable对象,用于捕获表达式运行错误或断言结果失败。(当然需要开启assert.exception)PHP>=7.0.0,支持zend.assertions,assert.exception相关配置及其特性PHP>=7.2版本,参数断言不再支持字符串,见PHP7.2。xfordetailsDeprecated:assert():Callingassert()withastringargumentisdeprecated应用场景调试输出先看例子:assert('1==2','1cannotbeequalto2');运行结果:Warning:assert():1cannotequal2:"1==2"failedin/Users/shocker/Desktop/demo.phponline10类似:$expression=1==2;if(!($expression)){echo"1不能等于2\n";变量转储($表达式);回声__FILE__。"\n";}但是,我们无法得知$expression的具体表达方式,也无法得知具体的执行行数。单元测试函数arraySum(array$nums){$sum=0;foreach($numsas$n){$sum+=$n;}return$sum;}assert(arraySum([1,2,3])==6,'arraySum()测试失败:');assert(is_numeric(arraySum([1,2,3])),'arraySum()测试失败:');是不是和我们用PHPUnit写单元测试很像?验证表达式提示:从PHP7开始,添加了一个新的Error类来捕获PHP的内置错误,包括语法错误。Error和之前的Exception都继承自Throwable,所以从7.0.0开始,Throwable可以捕获所有的错误和异常。以下示例演示了如何验证字符串表达式是否为有效的PHP表达式:try{assert('a+==1');}catch(Throwable$e){echo$e->getMessage(),"\n";}运行结果:失败求值代码:a+==1安全问题假设如下代码,结果会是什么?functiondemo(){file_put_contents('data.log','shockerli.net');返回真;}$func=$_GET["func"];assert("$func()");所以,对于assert函数,一般情况下不建议在生产环境中使用。和eval一样,它会执行任何PHP代码,危害极大。这就是PHP从7.2开始就不再支持字符串表达式的原因。感谢阅读,我觉得内容不错,喜欢吗?原文地址:https://shockerli.net/post/php-assert/
