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 如果为 false,则 assert() 不检查期望并始终返回 true 自 PHP 8.3.0 起已弃用。
assert.callback null

断言失败时要调用的用户定义函数。它的签名应该是

assert_callback(
    字符串 $file,
    整数 $line,
    null $assertion,
    字符串 $description = ?
):

在 PHP 8.0.0 之前,回调的签名应该是

assert_callback(
    字符串 $file,
    整数 $line,
    字符串 $assertion,
    字符串 $description = ?
):

自 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 之前,如果 assertion 是一个 字符串,则将其解释为 PHP 代码并通过 eval() 执行。此字符串将作为第三个参数传递给回调。此行为在 PHP 7.2.0 中已弃用,在 PHP 8.0.0 中已移除

description

如果 descriptionThrowable 的实例,则仅当 assertion 被执行并失败时才会抛出它。

注意:

从 PHP 8.0.0 开始,这在调用潜在定义的断言回调之前完成。

注意:

从 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')assert.quiet_eval php.ini 指令和 ASSERT_QUIET_EVAL 常量也已删除,因为它们将不再有任何效果。
8.0.0 如果 descriptionThrowable 的实例,则如果断言失败,则会抛出该对象,而不管 assert.exception 的值如何。
8.0.0 如果 descriptionThrowable 的实例,则即使设置了用户回调,也不会调用它。
8.0.0 在命名空间内声明名为 assert() 的函数不再允许,并且会发出 E_COMPILE_ERROR
7.3.0 在命名空间内声明名为 assert() 的函数已弃用。此类声明现在会发出 E_DEPRECATED
7.2.0 使用 字符串 作为 断言 已被弃用。当 assert.activezend.assertions 均设置为 1 时,现在会发出 E_DEPRECATED 通知。

示例

示例 #1 assert() 示例

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

如果启用了断言(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

如果禁用了断言(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 条注释

33
hodgman at ali dot com dot au
16 年前
如维基百科所述 - “断言主要是一种开发工具,在程序发布给公众时,它们通常会被禁用。” 以及“断言应该用于记录逻辑上不可能出现的情况并发现编程错误——如果'不可能'发生,那么显然某些基本的东西出了问题。这与错误处理不同:大多数错误条件都是可能的,尽管有些在实践中极不可能发生。将断言用作通用错误处理机制通常是不明智的:断言不允许从错误中优雅地恢复,并且断言失败通常会突然停止程序的执行。断言也不会显示用户友好的错误消息。”

这意味着“gk at proliberty dot com”给出的强制启用断言的建议,即使它们已被手动禁用,也违背了仅将它们用作开发工具的最佳实践。
9
sven at rtbg dot de
9 个月前
随着 PHP 8.3 中进行的当前更改(弃用影响断言的 INI 设置)以及越来越多的开源库利用 `assert()` 作为一种简单的方法来确保 PHP 核心函数调用的模糊返回情况实际上没有触发(例如,没有返回 NULL 或 FALSE,而是有用的值),关于断言仅作为开发过程中使用的工具的评论应该被认为是无效的。

此外,静态代码分析工具利用从 `assert($x instanceof MyClass)` 获得的知识来了解可能的类型或类型。

断言正在生产代码中积极使用,它们很有用,禁用它们只会获得最小的性能提升,因为断言表达式通常非常小。

在适用时使用此工具!
To Top