当我运行“Behat”步骤时,Behat error handler将“尝试获取非对象的属性”错误转换为异常。
这非常有用,因为它会导致步骤被标记为失败,并允许测试运行在下一个场景中继续。
但是,“调用非对象上的成员函数”错误是致命的,会立即停止测试执行(包括中止将结果写入 xml)。这是没有帮助的。
我的问题是:
这两个错误有什么区别?它们是不同的“错误级别”吗?在哪里记录?我搜索了 PHP 站点和 Google,找不到规范引用,只有很多关于调试每个错误的特定实例的问题。
有没有办法将后一个错误转换为异常,而不是完全停止脚本?在我看来,用“->”取消引用“null”不会是“无法从中恢复的错误,例如内存分配问题” .
更新:
看起来这只是 PHP 的一个已知问题。见:
有些人说这是“设计使然”,但我认为这只是在将对象添加到 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/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file