Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP自动加载:防止';无法重新声明<;类别>';在所有星座中? 问题:_Php_Autoload_Fatal Error_Redeclaration - Fatal编程技术网

PHP自动加载:防止';无法重新声明<;类别>';在所有星座中? 问题:

PHP自动加载:防止';无法重新声明<;类别>';在所有星座中? 问题:,php,autoload,fatal-error,redeclaration,Php,Autoload,Fatal Error,Redeclaration,有没有办法让PHP忽略类的重新声明,而不是抛出致命错误?或者至少抛出一个异常?(我可以很容易地捕获它并继续(以及记录尝试自动加载的日志)。) 我猜不是,致命错误是致命错误——毕竟,在百分之九十九的案例中,这是合理合理的行为——我可能只需要修复在个案基础上触发的实例。但也许比我聪明的人已经明白了这一点 如果你在问自己“你到底为什么要这么做?”,请继续读下去 背景 我正在开发一个工具,它使用反射来聚合有关所用函数和类的特定信息。脚本的一个参数是一个可选的引导文件,通过自动加载使反射更加可靠(较少的

有没有办法让PHP忽略类的重新声明,而不是抛出致命错误?或者至少抛出一个异常?(我可以很容易地捕获它并继续(以及记录尝试自动加载的日志)。)

我猜不是,致命错误是致命错误——毕竟,在百分之九十九的案例中,这是合理合理的行为——我可能只需要修复在个案基础上触发的实例。但也许比我聪明的人已经明白了这一点


如果你在问自己“你到底为什么要这么做?”,请继续读下去

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

现在,引导会很好地加载自动加载器,脚本按预期运行,毫无怨言地在数百个文件中移动,直到遇到一个障碍:

PHP致命错误:无法重新声明类 中的PHPUnit_框架_约束 /usr/share/php/PHPUnit/Framework/Constraint.php 第62行

我有两个问题:

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

第二,更重要的是,我需要一种方法来抓住这个问题的主题。我尝试过编写一个自定义错误处理程序,但它似乎不想为
致命错误
s工作(有人可能会认为这是合理的)

我打算在某个时候将这个工具发布到开源世界中,这让我觉得是一个非常不可接受的行为。对于不存在的类,我有一个回退启发式-我宁愿它们很少声明一次,而不是经常声明一次,但也不要过度使用启发式,也就是说,我确实希望提供使用引导程序的功能而不破坏脚本。曾经。即使它是自动装弹机历史上最差的自动装弹机


(强调:我不需要自动加载器方面的帮助。这不是这个问题的重点。

避免
无法重新声明的最佳选择之一是
class\u exists
函数。您可以在自动加载器中使用它来防止类重新声明。使用
class_exists
您不必捕获错误,只需防止它

实际上有两种致命错误:可捕获和不可捕获。类重新声明不会引发
E\u RECOVERABLE\u错误
(可捕获的错误),您无法处理它


因此,您的问题的答案是:“您不能。”

自动加载不会自动尝试加载已加载的类。如果您有>1个同名的类,您可能会做错

如果解析“不安全”的代码,您可能希望在加载类名之前搜索该文件,但这只能作为最后的手段,因为这是对CPU的巨大浪费,可能只是隐藏了有效的bug


如果您有一个require结构和一个自动加载系统,那么您可能会在autoload中包含一个文件,然后再在require中包含一个文件。如果(class_exists(){……}
我不知道您是否仍然对答案感兴趣,但我遇到的问题可能与您在混合自动加载和反射时遇到的问题相同。以下是我关于自动加载失败原因的假设:

spl\u autoload\u register
对它使用完全指定的名称间隔的类标识符自动加载的类和从名称空间中加载的类(使用不包含名称空间的类标识符)进行了区分。据我所知,这是一个bug


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

该工具在做什么?类似这样的事情?PHP的自动加载功能不应该有这样的问题问题是,如果你使用
include_once
包含文件,你也不应该这样做。你具体在做什么?@Gordon:工具本身使用反射来获取类的信息。它本身与自动加载无关,它只是利用它。@deceze:我最初使用Zend的自动加载程序来加载文件,然后使用alternate方法与'just'SPL的自动加载堆栈。这两种方法都会导致问题。我非常确定,如果我花更多时间使用它,我可能会修复这个失败的特定实例,但这并没有改变,我希望脚本在可能的情况下一般都能防止这种情况。(更多信息请在第二条评论中跟进。)我的脚本除了使用标记器、提取被调用的函数和实例化的或类型提示的类,以及通过反射(或基于启发式猜测信息)聚合信息之外,什么都不做。也就是说,它不需要加载类,甚至不需要正确加载,但最好是尽可能多地正确加载类,而不是因为一个类在
include\u路径中的两个位置可用而中止。(这就是我怀疑正在发生的事情。不管怎样,这通常是导致自动加载中“无法重新声明”错误的原因。尽管如此,如上所述,我还没有找到答案。)