Bonne question. Je pense que c'est un problème général avec E_RECOVERABLE_ERROR
PHP.
Ce que vous avez dans votre question est le gestionnaire d'exceptions, pas le gestionnaire d'erreurs. Le gestionnaire d'erreurs est à l'origine du problème réel dont vous discutez ici avec des erreurs fatales capturables ( E_RECOVERABLE_ERROR
) .
PHP 7 et HHVM ont déjà résolu ce problème.
C'est pire avec Magento car le gestionnaire d'erreurs ne gère pas cela depuis la classe d'erreur PHP 5.2.
Un type plus utile de gestion des erreurs consisterait à traiter cette classe d’erreurs et à transformer ces erreurs en erreurs d’ exception . Exemple (pas par moi, d'ici ):
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
return false;
});
Donc, à la lumière de Magento, le gestionnaire d'erreurs par défaut est la fonction globale mageCoreErrorHandler
dans app/code/core/Mage/Core/functions.php
. Il est enregistré via Mage::app()
la init()
méthode de Mage_Core_Model_App ( app/code/core/Mage/Core/Model/App.php
) (via la _initEnvironment()
méthode protégée ).
Un observateur surcontroller_front_init_before
lequel enregistre votre propre gestionnaire d'erreurs PHP devrait suffire (les gestionnaires d'erreurs en PHP sont empilables):
$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;
});
les erreurs fatales capturables sont ensuite transformées en exceptions et vous pouvez les traiter dans votre propre code d'extension ou elles ne sont pas détectées et seront vues dans le journal des exceptions (au lieu d'avoir votre boutique exécutez gaga sur des types incorrects comme le comportement actuel, les programmes morts) ne mentez pas ). En PHP 7, l'exception à rechercher n'est pas alors ErrorException mais TypeException (qui est une BaseException ) pour les erreurs fatales désormais capturables .
Toutes les autres erreurs sont transmises au gestionnaire d'erreurs de Magento.
Remarque: je n'ai pas essayé cela, c'est une description mais je connais le problème que vous posez et l'analyse de la gestion des erreurs a été effectuée par rapport à 1.5.1.0 et vérifiée par rapport à 1.9.1.0 via l'analyse de code. L'empilement du gestionnaire d'erreurs devrait fonctionner. J'ajoute un petit exemple de code étendu qui montre que la plupart des pièces fonctionnent.
Je n'ai pas encore emballé cela comme une extension magento mais cela devrait être simple avec modman. Je vais le mettre sur github alors.
Annexe: Démo du gestionnaire d'erreurs
L'exemple de code suivant ( démonstration en ligne ) illustre l'empilement de gestionnaires d'erreurs et le lancement d'exceptions en cas d' erreur fatale capturable :
<?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
Sortie du programme
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