Гарне питання. Я думаю, це загальна проблема 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, але це повинно бути прямо вперед з модменом. Я тоді покладу його на 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