Boa pergunta. Eu acho que esse é um problema geral E_RECOVERABLE_ERROR
no PHP.
O que você tem na sua pergunta é o manipulador de exceções, não o manipulador de erros. O manipulador de erros está causando o problema real que você discute aqui com erros fatais capturáveis ( E_RECOVERABLE_ERROR
) .
PHP 7 e HHVM já resolveram isso.
É pior com o Magento porque o manipulador de erros não lida com isso desde a classe de erro do PHP 5.2.
Um tipo mais útil de tratamento de erros seria lidar com essa classe de erro e transformá-los em ErrorException s. Exemplo (não por mim, daqui ):
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
return false;
});
Portanto, à luz do Magento, o manipulador de erros padrão é a função global mageCoreErrorHandler
no app/code/core/Mage/Core/functions.php
. Ele é registrado via Mage::app()
pelo init()
método Mage_Core_Model_App ( app/code/core/Mage/Core/Model/App.php
) (via _initEnvironment()
método protegido ).
Um observador nocontroller_front_init_before
qual registra seu próprio manipulador de erros PHP no topo deve ser suficiente (os manipuladores de erros no PHP são empilháveis):
$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;
});
erros fatais capturáveis são transformados em exceções e você pode lidar com eles em seu próprio código de extensão ou eles são detectados e serão vistos no log de exceções (em vez de fazer com que sua loja execute gaga com tipos errados, como o comportamento atual, programas mortos não minta ). No PHP 7, a exceção a procurar não é ErrorException , mas TypeException (que é uma BaseException ) para os erros fatais agora capturáveis .
Todos os outros erros são passados para o manipulador de erros do Magento.
Nota: Eu não tentei isso, é uma revisão, mas eu sei o problema que você está perguntando e a análise de tratamento de erros foi feita na 1.5.1.0 e verificada na 1.9.1.0 através da análise de código. O empilhamento do manipulador de erros deve funcionar. Anexo um pequeno código de exemplo estendido que demonstra a maioria das peças funcionando.
Ainda não o empacotei como uma extensão magento, mas deve ser direta com o modman. Vou colocá-lo no github então.
Apêndice: Demonstração do Manipulador de Erros
O seguinte exemplo de código ( demonstração online ) demonstra o empilhamento de manipuladores de erros e a exceção lançando um erro fatal capturável :
<?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
Saída do Programa
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