คำถามที่ดี. ฉันคิดว่านี่เป็นปัญหาทั่วไปE_RECOVERABLE_ERROR
ใน PHP
สิ่งที่คุณมีในคำถามของคุณคือตัวจัดการข้อยกเว้นไม่ใช่ตัวจัดการข้อผิดพลาด ข้อผิดพลาดการจัดการที่เป็นสาเหตุของปัญหาที่เกิดขึ้นจริงที่คุณพูดคุยที่นี่มีข้อผิดพลาดร้ายแรง catchable (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;
});
ดังนั้นในแง่ของวีโอไอพี, ข้อผิดพลาดของตัวจัดการเริ่มต้นคือฟังก์ชั่นระดับโลกใน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;
});
ข้อผิดพลาดร้ายแรง catchableแล้วจะกลายเป็นข้อยกเว้นและคุณสามารถจัดการกับพวกเขาในรหัสนามสกุลของคุณเองหรือพวกเขาจะไม่ถูกตรวจจับและจะเห็นได้ในบันทึกข้อยกเว้น (แทนที่จะต้อง gaga ร้านทำงานของคุณเกี่ยวกับประเภทที่ไม่ถูกต้องเช่นพฤติกรรมในปัจจุบันมีโปรแกรมที่ตายแล้ว อย่าโกหก ) ใน PHP 7 ข้อยกเว้นที่จะมองหาไม่ErrorExceptionแล้ว แต่TypeException (ซึ่งเป็นBaseException ) สำหรับตอนนี้ข้อผิดพลาดร้ายแรง catchable
ข้อผิดพลาดอื่น ๆ ทั้งหมดจะถูกส่งไปยังตัวจัดการข้อผิดพลาดของ Magento
หมายเหตุ: ฉันไม่ได้ลองสิ่งนี้มันเป็นบทความ แต่ฉันรู้ว่าปัญหาที่คุณถามและการวิเคราะห์การจัดการข้อผิดพลาดได้ทำกับ 1.5.1.0 และตรวจสอบกับ 1.9.1.0 ผ่านการวิเคราะห์รหัส การจัดการตัวจัดการข้อผิดพลาดควรทำงาน ฉันผนวกรหัสตัวอย่างเพิ่มเติมเล็กน้อยที่แสดงถึงการทำงานส่วนใหญ่
ฉันยังไม่ได้บรรจุสิ่งนี้เป็นส่วนขยายของวีโอไอพี แต่ควรตรงไปตรงมากับ 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