Хороший вопрос. Я думаю, что это общая проблема E_RECOVERABLE_ERROR
в PHP.
В вашем вопросе есть обработчик исключений, а не обработчик ошибок. Обработчик ошибок вызывает реальную проблему, которую вы обсуждаете здесь, с обнаруживаемыми фатальными ошибками ( E_RECOVERABLE_ERROR
) .
В PHP 7 и HHVM это уже решено.
С Magento хуже, потому что обработчик ошибок не работает с этим, начиная с класса ошибок PHP 5.2.
Более полезным видом обработки ошибок будет иметь дело с этим классом ошибок и превращать эти ошибки в ErrorException s. Пример (не мной, отсюда ):
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