好问题。我认为这是E_RECOVERABLE_ERROR
PHP中的普遍问题。
问题中的内容是异常处理程序,而不是错误处理程序。错误处理程序引起您在此处讨论的实际问题,并带有可捕获的致命错误(E_RECOVERABLE_ERROR
)。
PHP 7和HHVM已经解决了这一问题。
Magento的情况更糟,因为自PHP 5.2错误类以来,错误处理程序不再对此进行处理。
一种更有用的错误处理方法是处理此类错误,并将这些错误转换为ErrorException。示例(不是我的,从这里开始):
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
return false;
});
所以,在Magento的光,默认的错误处理程序是全局函数mageCoreErrorHandler
中app/code/core/Mage/Core/functions.php
。它得到通过注册的Mage::app()
由init()
该法Mage_Core_Model_App(app/code/core/Mage/Core/Model/App.php
)(通过保护_initEnvironment()
法)。
这样,在controller_front_init_before
其上面注册了您自己的PHP错误处理程序的观察者就足够了(PHP中的错误处理程序是可堆栈的):
$previous = set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$previous) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
if ($previous) {
return call_user_func($previous, $errno, $errstr, $errfile, $errline);
}
return false;
});
可捕获的致命错误然后变成异常,您可以在自己的扩展代码中对其进行处理,或者将它们捕获,并在异常日志中看到它们(而不是让商店对当前类型为错误的错误类型执行加加,死程序不要说谎)。在PHP 7中,要查找的异常不是ErrorException,而是 TypeException(这是一个BaseException)对于现在开捕致命错误。
所有其他错误都传递给Magento的错误处理程序。
注意:我还没有尝试过,这是一篇文章,但我知道您要问的问题,并且针对代码1.5.1.0进行了错误处理分析,并通过代码分析针对1.9.1.0进行了验证。错误处理程序堆栈应该可以工作。我附加了一些扩展的示例代码,以演示大多数部分的工作原理。
我还没有将其打包为magento扩展,但应该与modman一起使用。然后将其放在github上。
附录:错误处理程序演示
以下代码示例(在线演示)演示了错误处理程序的堆栈以及在可捕获的致命错误上引发的异常:
<?php
/**
* error handler demonstration
*
* stackable error handle with previous call and catchable error exceptions
*
* @author hakre <http://hakre.wordpress.com>
* @link /magento//a/64972/4115
*/
set_error_handler(function() {
$args = func_get_args();
var_dump("me is the previous error handler", $args);
});
$previous = set_error_handler(function($errno, $errstr, $errfile, $errline) use (&$previous) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
if ($previous) {
return call_user_func($previous, $errno, $errstr, $errfile, $errline);
}
return false;
});
$test = function(callable $test) {};
$a = $undefined; // provoke little warning
$test(new stdClass); // provoke catchable fatal error
节目输出
string(32) "me is the previous error handler"
array(4) {
[0]=>
int(8)
[1]=>
string(29) "Undefined variable: undefined"
[2]=>
string(45) "/tmp/execpad-0eca072b619d/source-0eca072b619d"
[3]=>
int(28)
}
Fatal error: Uncaught exception 'ErrorException' with message 'Argument 1 passed to {closure}() must be callable, object given, called in /tmp/execpad-0eca072b619d/source-0eca072b619d on line 30 and defined' in /tmp/execpad-0eca072b619d/source-0eca072b619d:26
Stack trace:
#0 /tmp/execpad-0eca072b619d/source-0eca072b619d(26): {closure}(4096, 'Argument 1 pass...', '/tmp/execpad-0e...', 26, Array)
#1 /tmp/execpad-0eca072b619d/source-0eca072b619d(30): {closure}(Object(stdClass))
#2 {main}
thrown in /tmp/execpad-0eca072b619d/source-0eca072b619d on line 26