原来一直以为断言相关的函数是 PHPUnit 这些单元测试组件提供的,在阅读手册后才发现,这个 assert() 断言函数是 PHP 本身就自带的一个函数。也就是说,我们在代码中进行简单的测试的时候是不需要完全引入整个单元测试组件的。

assert() 断言函数


assert(1==1); assert(1==2);
// assert.exception = 0 时,Warning: assert(): assert(1 == 2)
// assert.exception = 1 时,Fatal error: Uncaught AssertionError: 验证不通过

很明显,第二段代码无法通过断言验证。这时,PHP 就会返回一个警告或者异常错误。为什么有可能是两种错误形式呢?当我们设置 php.ini 中的 assert.exception 为 off 或者 0 时,也就是关闭这个参数的能力时,程序就会以 PHP5 的形式依然返回一个警告,就像上面代码中的注释一样。同时,通过 try...catch 也无法进行异常的捕获了。这个参数其实就是控制是否以正宗的异常对象进行抛出。如果保持这个参数为默认情况也就是设置为 on 或者 1 的话,就会直接抛出异常,程序中止。

从上述代码可以看出,断言的第一个参数是一个表达式,而且是需要一个返回 bool 类型对象的表达式。如果我们传递的是一个字符串或者一个数字呢?

// 设置 assert.exception = 0 进行多条测试

assert(" ");
// Deprecated: assert(): Calling assert() with a string argument is deprecated
// Warning: assert(): Assertion " " failed assert("1");
// Deprecated: assert(): Calling assert() with a string argument is deprecated assert(0);
// Warning: assert(): assert(0) failed assert(1); assert("1==2");
// Deprecated: assert(): Calling assert() with a string argument is deprecated
// Warning: assert(): Assertion "1==2" failed

很明显第一个参数的表达式会进行类型强制转换,但是字符串类型会多出一个过时提醒,表明给 assert() 函数传递字符串类型的表达式类型已经过时了。当前的测试版本是 7.3 ,在将来可能就会直接报中止运行的错误或异常了。主要问题在于,如果传递的字符串本身也是一个表达式的话,会以这个表达式的内容为基础进行判断,这样很容易产生歧义,就像最后一段代码一样。当然,已经过时的使用方式还是不推荐的,这里仅是做一个了解即可。

接下来我们看一下 assert() 函数的其他参数,它的第二个参数是两种类型,要么给一个字符串用来定义错误的信息,要么给一个 异常类 用于抛出异常。

assert(1==1, "验证不通过");

assert(1==2, "验证不通过");
// Warning: assert(): 验证不通过 failed

如果直接给的一个字符串,那么在警告的提示信息中,显示的就是我们定义的这个错误信息的内容。这个非常好理解。

// 注意 assert.exception 设置不同的区别

assert(1==1,  new Exception("验证不通过"));

assert(1==2,  new Exception("验证不通过"));
// assert.exception = 1 时,Fatal error: Uncaught Exception: 验证不通过
// assert.exception = 0 时,Warning: assert(): Exception: 验证不通过

当然,我们也可以给一个 异常类 让断言抛出一个异常。在默认情况下,这个异常的抛出将中止程序的运行。也就是一个正常的异常抛出流程,我们可以使用 try...catch 进行异常的捕获。

try{
assert(1==2, new Exception("验证不通过"));
}catch(Exception $e){
echo "验证失败!:", $e->getMessage(), PHP_EOL;
}
// 验证失败!:验证不通过

另外还有一个参数会对断言的整体运行产生影响,那就是 php.ini 中的 zend.assertions 参数。它包含三个值:

  • 1,生成并执行代码,一般在测试环境使用
  • 0,生成代码但是在运行时会路过
  • -1,不生成代码,一般在正式环境使用

这个参数大家可以自行配置测试,默认的 php.ini 中它的默认值是 1 ,也就是正常的执行 assert() 函数。

assert_options() 及相对应的 php.ini 中的参数配置

PHP 中的断言功能还为我们提供了一个 assert_options() 函数,用于方便地设置和获取一些和断言能力有关的参数配置。它能够设置的断言标志包括:

标志 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_CALLBACK 的作用。其实它的说明也非常清楚,就是断言失败的情况下就进入到这个选项定义的回调函数中。

assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 1);
assert_options(ASSERT_BAIL, 1); assert_options(ASSERT_CALLBACK, function($params){
echo "====faild====", PHP_EOL;
var_dump($params);
echo "====faild====", PHP_EOL;
}); assert(1!=1);
// ====faild====
// string(105) ".../source/一起学习PHP中断言函数的使用.php"
// ====faild====

当断言失败的时候,我们就进入了回调函数中,在回调函数直接简单的打印了传给回调函数的参数内容。可以看出,这个回调函数里面传递过来的是无法通过断言的文件信息。

总结

学习掌握一下断言函数的使用及配置,可以为我们将来学习 PHPUnit 单元测试打下基础,当然,本身这个能力的东西就不是很多,大家记住就好啦!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202005/source/%E4%B8%80%E8%B5%B7%E5%AD%A6%E4%B9%A0PHP%E4%B8%AD%E6%96%AD%E8%A8%80%E5%87%BD%E6%95%B0%E7%9A%84%E4%BD%BF%E7%94%A8.php

参考文档:

https://www.php.net/manual/zh/function.assert-options.php

https://www.php.net/manual/zh/function.assert.php

一起学习PHP中断言函数的使用的更多相关文章

  1. C++学习笔记32 断言函数

    首先,让我们来看看百度百科上"断言函数"定义说明: 1定义fr=aladdin#" class="nslog:1019" title="编辑 ...

  2. 带你学习Javascript中的函数进阶(一)

    1. 函数的定义和调用 1.1 函数的定义方式 函数声明方式function关键字(命名函数) 函数表达式(匿名函数) new Function() var fn = new Function('参数 ...

  3. SQL中随机数函数rand()简介

    转自:http://database.51cto.com/art/201009/224397.htm 下文将为您介绍SQL中的随机函数rand(),供您参考,如果您是才接触SQL Server的新手, ...

  4. 前端学习 第六弹: javascript中的函数与闭包

    前端学习 第六弹:  javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) {   ...

  5. 关于C/C++中main函数参数的学习

    因为面对对象作业(2018.5.21)的要求,去学习了C/C++中main函数参数的意义,以及一些简单的使用(从命令行指令的接受),不给予赘述.(仅为个人拙见,还望看官指正) 首先,带有参数的main ...

  6. [原创]java WEB学习笔记42:带标签体的自定义标签,带父标签的自定义标签,el中自定义函数,自定义标签的小结

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. 从极大似然估计的角度理解深度学习中loss函数

    从极大似然估计的角度理解深度学习中loss函数 为了理解这一概念,首先回顾下最大似然估计的概念: 最大似然估计常用于利用已知的样本结果,反推最有可能导致这一结果产生的参数值,往往模型结果已经确定,用于 ...

  8. C++ 中assert断言函数的基本用法

    在我们的实际开发过程之中,常常会出现一些隐藏得很深的BUG,或者是一些概率性发生的BUG,通常这些BUG在我们调试的过程中不会出现很明显的问题,但是如果我们将其发布,在用户的各种运行环境下,这些程序可 ...

  9. C语言学习_C如何在一个文件里调用另一个源文件中的函数

    问题 C如何在一个文件里调用另一个源文件中的函数,如题. 解决办法 当程序大了代码多了之后,想模块化开发,不同文件中存一点,是很好的解决办法,那我们如何做才能让各个文件中的代码协同工作呢?我们知道,m ...

随机推荐

  1. SpringBoot开发十二-账号设置

    需求介绍-账号设置 账号设置里面的上传头像(文件) 首先请求必须是一个 POST 请求,其次表单的属性 enctype = "multipart/form-data" 然后就是利用 ...

  2. 接入华为应用内支付,验证购买Token接口,返回“rights invalid”

    有海外开发者向我们提问:我在应用中集成了华为应用内支付SDK(测试购买订阅型商品),按照文档说明,在服务器去请求验证购买Token接口的时候返回了{"responseCode":& ...

  3. NOIP 模拟 $16\; \rm Star Way To Heaven$

    题解 \(by\;zj\varphi\) 看懂题!!! 从最左穿到最右,一定会经过两个星星之间或星星和边界之间,那么我们穿过时当前最优一定是走中点 而我们要求最小的距离最大,那么我们将所有星星和边界( ...

  4. 心态崩了,我怎么知道实际生产环境的 B+ 树索引有多少层?

    Q:在实际生产环境中,InnoDB 中一棵 B+ 树索引一般有多少层?可以存放多少行数据? 关于这个问题最近好像在牛客上经常看到,感觉没啥意义,可能主要考察的是对 B+ 索引的理解吧.先上答案: A: ...

  5. SSM自学笔记(二)

    3.SpringMVC入门 1.Spring与Web环境集成 1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplication ...

  6. 6、二进制安装K8s之部署kubectl

    二进制安装K8s之部署kubectl 我们把k8s-master 也设置成node,所以先master上面部署node,在其他机器上部署node也适用,更换名称即可. 1.在所有worker node ...

  7. VS 添加自定义--代码块 实现一秒创建方法

    创建一个方法 你是不是不可避免需要敲以下至少6行代码 现在教你一个方法 实现一秒创建完整方法 首先按照代码块规则创建代码块文件 代码块意义,是什么? 请参考: https://docs.microso ...

  8. C#多线程详解(二)

    在上一节介绍了线程的基础知识,下面来研究多线程的优先级 using System; using System.Threading;namespace Test{    class TestThread ...

  9. msql中@RequestParam、@Param、@PathVariable的用法

    @RequestParam的用法 1.可以对传入参数指定参数名,将请求参数绑定至方法参数 // 下面的对传入参数指定为aa,如果前端不传aa参数名,会报错 @RequestParam(value=&q ...

  10. 一:Tomcat安装、配置和部署笔记

    Tomcat安装(绿色版安装) 1.将下载的Tomcat解压到指定目录,如:D:\WorkSpaceByJava\DevtTools\Apache-Tomcat-8.0.23 2.Tomcat的目录结 ...