Pertanyaan bagus. Saya pikir ini adalah masalah umum E_RECOVERABLE_ERROR
dalam PHP.
Apa yang Anda miliki dalam pertanyaan Anda adalah penangan pengecualian, bukan penangan kesalahan. Penangan kesalahan menyebabkan masalah aktual yang Anda diskusikan di sini dengan kesalahan fatal yang dapat ditangkap ( E_RECOVERABLE_ERROR
) .
PHP 7 dan HHVM sudah menyelesaikan ini.
Ini lebih buruk dengan Magento karena penangan kesalahan tidak berurusan dengan ini sejak kelas kesalahan PHP 5.2.
Jenis penanganan kesalahan yang lebih bermanfaat adalah menangani kelas kesalahan ini dan mengubah kesalahan ini menjadi ErrorException s. Contoh (bukan oleh saya, dari sini ):
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if ($errno === E_RECOVERABLE_ERROR) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
return false;
});
Jadi dalam terang Magento, penangan kesalahan default adalah fungsi global mageCoreErrorHandler
di app/code/core/Mage/Core/functions.php
. Itu bisa didaftarkan melalui Mage::app()
olehinit()
metode yang Mage_Core_Model_App ( app/code/core/Mage/Core/Model/App.php
) (via dilindungi _initEnvironment()
metode).
Sebuah pengamatcontroller_front_init_before
yang mendaftarkan penangan kesalahan PHP Anda sendiri di atas sudah cukup maka (penangan kesalahan dalam PHP dapat ditumpuk):
$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;
});
kesalahan fatal yang dapat ditangkap kemudian diubah menjadi pengecualian dan Anda dapat menanganinya dalam kode ekstensi Anda sendiri atau tidak tertangkap dan akan terlihat di log pengecualian (alih-alih toko Anda menjalankan gaga pada jenis yang salah seperti perilaku saat ini, program yang mati jangan bohong ). Dalam PHP 7 pengecualian untuk mencari tidak ErrorException itu tapi TypeException (yang merupakan BaseException ) untuk kesalahan fatal yang sekarang dapat ditangkap .
Semua kesalahan lain diteruskan ke penangan kesalahan Magento.
Catatan: Saya belum mencoba ini, ini adalah artikel tetapi saya tahu masalah yang Anda tanyakan dan analisis penanganan kesalahan telah dilakukan terhadap 1.5.1.0 dan diverifikasi terhadap 1.9.1.0 melalui analisis kode. Penumpukan penangan kesalahan harus berhasil. Saya menambahkan sedikit contoh kode yang menunjukkan sebagian besar komponen berfungsi.
Saya belum mengemas ini sebagai ekstensi magento tetapi harus lurus ke depan dengan modman. Saya akan menaruhnya di github.
Lampiran: Demo Handler Demo
Contoh kode berikut ( demo online ) menunjukkan penumpukan penangan kesalahan dan pengecualian terhadap kesalahan fatal yang dapat ditangkap :
<?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
Output Program
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