PHP自动加载:在所有星座中防止“无法重新声明<class>”?</class>

时间:2010-07-14 12:42:52

标签: php autoload fatal-error redeclaration

问题

有没有办法让PHP 忽略重新声明类而不是barf up a fatal ERROR?或者至少抛出异常?(我可以很容易地抓住它并继续(以及尝试自动加载的日志)。)

我猜不是,致命错误是一个致命的错误 - 毕竟,在百分之九十九的案例中,这是一个相当合理的行为 - 我可能只需要修复它被触发的实例个案基础。但也许比我更聪明的人想到了这一点。


如果你问自己“为什么你想要这样做?”,请继续阅读。

背景

我正在开发一个使用 Reflection 来聚合有关已使用函数和类的特定信息的工具。脚本的一个参数是一个可选的引导文件,通过自动加载使 Reflection 更可靠(更少ReflectionExceptions最终被捕获并触发回退启发式,因为类在特定文件中是未知的)

现在,bootstrapping正好加载了自动加载器,脚本按预期运行,在没有任何投诉的情况下移动了几百个文件,直到我遇到麻烦:

  

PHP致命错误:无法重新声明课程   PHPUnit_Framework_Constraint in   /usr/share/php/PHPUnit/Framework/Constraint.php   第62行

我有两个问题:

一,我不知道是什么触发了这一点。我已经调整了所使用的引导程序,但只是在“无法重新声明”和“无法打开文件”之间交替,具体取决于所使用的包含路径。没有中间立场,即没有发生错误的点。不过,我还在调查。 (但这个问题不是问题所在。)

两个,更重要的是,并且导致了这个问题的主题,我需要一种方法来抓住它。我已经尝试过编写一个自定义错误处理程序,但似乎并不想为Fatal error工作(有些人可能会认为这有点明智)。

我打算在某个时候将这个工具发布到开源世界,这让我觉得这是一个非常不可接受的行为。对于不存在的类,我有一个后备启发式 - 我宁愿它们过于频繁地被宣布过一次,但是没有 over - 使用启发式,也就是说, ,我确实想提供使用引导程序的功能。 不破坏脚本。永远。即使它是自动加载器历史上最差的自动加载器。

(强调:我不想帮助我的自动加载器。这不是这个问题的关键。

3 个答案:

答案 0 :(得分:8)

避免Cannot redeclare的最佳选择之一是class_exists功能。您可以在自动装带器中使用它来防止类重新声明。使用class_exists您无需捕获错误,您只需阻止它。

实际上有两种致命错误:可捕获而不能捕获。类重新声明不会启动E_RECOVERABLE_ERROR(一个可捕获的)并且您无法处理它。

所以,你的问题的答案是:“你做不到。”

答案 1 :(得分:3)

我不知道您是否仍然对答案感兴趣,但我遇到了混合自动加载和反射时遇到的相同问题。以下是关于自动加载失败原因的假设:

spl_autoload_register区分了自动加载的类和完全指定的名称间隔类标识符,以及从名称空间内加载的类,这些类具有不包含名称空间的类标识符。据我所知,这是一个错误。

我的解决方案:我在创建反射类实例之前进行测试,如果类标识符是完全名称间隔的。如果不是,我不使用反射。由于您不介意某些类没有加载,这也可能是您问题的解决方案。

答案 2 :(得分:2)

Autoload永远不会自动尝试加载已加载的类。如果你有&gt; 1个同名的班级你可能做错了。

如果你解析“不安全”的代码,你可能想在尝试加载它之前在文件中搜索类名,但是这只应该作为最后的手段使用,因为它会浪费大量CPU并且可能只是隐藏有效的错误。

如果您有一个需要的结构和一个自动加载系统,您可能会在自动加载中包含一个文件,然后再次在require中。您可以通过使用if( class_exists( <class_name_string> ) { ... <class declaration in here> ... }

包装类来修复修复