PHP 将 "Call to a member function on a non-object"变成异常

标签 php error-handling

当我运行“Behat”步骤时,Behat error handler将“尝试获取非对象的属性”错误转换为异常。

这非常有用,因为它会导致步骤被标记为失败,并允许测试运行在下一个场景中继续。

但是,“调用非对象上的成员函数”错误是致命的,会立即停止测试执行(包括中止将结果写入 xml)。这是没有帮助的。

我的问题是:

  1. 这两个错误有什么区别?它们是不同的“错误级别”吗?在哪里记录?我搜索了 PHP 站点和 Google,找不到规范引用,只有很多关于调试每个错误的特定实例的问题。

  2. 有没有办法将后一个错误转换为异常,而不是完全停止脚本?在我看来,用“->”取消引用“null”不会是“无法从中恢复的错误,例如内存分配问题” .

更新:

看起来这只是 PHP 的一个已知问题。见:

  • #51882调用非对象的成员函数应该抛出异常
  • #46601 E_RECOVERABLE_ERROR 表示“调用非对象的成员函数”
  • #51848非对象方法调用错误应该可以用 set_error_handler() 捕获
  • #63538 “调用未定义的函数”应该是可捕获的

有些人说这是“设计使然”,但我认为这只是在将对象添加到 PHP 之前定义的错误级别的产物。在非 OO 语言中调用不存在的函数是一个严重的错误,我可以看到它如何被描述为“致命”或“不可恢复”(尽管在非 OO 语言中可以定义函数-苍蝇,即使这似乎过于悲观)。如今,既然您可以在任何旧的 $a 上执行“$a->f()”,那么“f"可能不存在,它似乎不应该是 fatal error (参见 Java,其中这将是 NullPointerException)。

我想这引出了一个新问题:

_ 3. 如何修补 PHP 以使“调用非对象上的成员函数”错误成为非 fatal error ,同时又不会严重破坏向后兼容性,以及您可以采取哪些步骤来最大限度地提高该修补程序的可能性接受到 PHP?

更新 2 重新修补 PHP:

有一些有限的支持on the PHP internals mailing list进行此修复。现在我只需要编写一个补丁来解决这个问题并创建一个 RFC。

最佳答案

问题是您可以动态声明对象的属性,但不能动态声明方法。 因此,如果您尝试在非对象上调用方法,则会收到 fatal error ,因为 PHP 无法确定该函数是否存在。

检查 this codepad对于一些带有错误号的简单输出。

现在仔细看看关于“设置和访问未设置属性”的部分。您可以看到 PHP 给您一条消息“正在从空值创建默认对象”。所以如果一个类不存在,PHP 会为你创建它。使用类型转换时也会发生同样的情况,请参阅 object typecasting

因此您可以访问非对象的属性,因为它将在动态创建的默认对象中检查该属性。但是,如果您访问一个方法,该默认对象仍然没有该方法。

这就是为什么属性返回 8 级错误而方法返回 1 级错误的原因(参见 error levels )。 由于它返回 1 级 fatal error ,您无法在此过程后继续。

关于PHP 将 "Call to a member function on a non-object"变成异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15502559/

相关文章:

excel - 当数组为空时处理错误 9

sql-server - SQL Server : conversion error when attempting to load 'smallmoney' data into table

c - 如何像 gets_s() 一样调用无效的处理函数?

javascript - 处理Node js中的多个错误

php - 静态函数可以访问php中的非静态变量吗?

php - 防止将空数组插入数据库。 PHP

php - php mysql替换中的英镑符号问题

php - 我正在尝试输入并显示名称和密码,但提交按钮没有任何反应?

java - 简单的: Java how to use “isRunning” on an audio clip?

php - 使用 MySQL 关系表循环行