मैगेंटो में न्यूट्रर्ड प्रकार की हिंटिंग से निपटना


15

बस सोच रहा था कि किसी के पास बेहतर रणनीति है जैसे मैंने टाइप करने के लिए सोचा था कि मैगेंटो के कस्टम त्रुटि हैंडलर के साथ सह-अस्तित्व है। विशेष रूप से, मैं "कैटलेबल फेटल एरर्स" के बारे में सोच रहा हूं जो कि टाइप किए हुए पैरामीटर बेमेल के मामले में फेंका जाता है। यहाँ Mageकक्षा से एक उदाहरण दिया गया है :

/**
 * Write exception to log
 *
 * @param Exception $e
 */
public static function logException(Exception $e)
{
    if (!self::getConfig()) {
        return;
    }
    $file = self::getStoreConfig('dev/log/exception_file');
    self::log("\n" . $e->__toString(), Zend_Log::ERR, $file);
}

त्रुटि हैंडलर के कारण, विधि के लिए कुछ भी पारित किया जा सकता है, जिसमें एक Zend_Date(जो ठीक काम करेगा, लेकिन आपके अपवाद लॉग में सुपर भ्रामक दिखता है), या एक Mage_Core_Model_App, जिसमें वास्तव में एक घातक त्रुटि होगी।

किसी विधि के शीर्ष पर पुन: जाँच करना संभव है: $e instanceof Exception लेकिन इस तरह की रणनीति एक टाइपहिंट के उद्देश्य को पराजित करती है।

कोई संकेत सुझाव?

जवाबों:


5

अच्छा सवाल +1

मेरे पहले जवाब पर @mpw के साथ चर्चा के बाद दिशा में एक अच्छे बिंदु के बाद कुछ शोध और परीक्षण किए। मैंने पहली बार इसे गलत समझा।

कुछ कोड को स्पष्ट करने के लिए जोड़ देगा ताकि अन्य इस मुद्दे को बेहतर ढंग से समझ सकें।

नोट बंद करने से पहले

जब तक यह सामने नहीं आया तब तक मुझे ऐसी कोई समस्या नहीं थी। डेवलपर मोड के साथ Magento में विकसित करने से मुझे इस बारे में एक सेकंड भी नहीं लगता है। इसलिए हर बार जब मैं फार्ट करता हूं , तो यह दिखाई देगा और उसी के अनुसार सही किया जाएगा।

एक समझाने वाले नमूने के साथ समस्या

आपकी कहावत घातक त्रुटियां लॉग की जाएंगी (यदि सक्षम की गई हैं) और कोड हमेशा की तरह जारी रहेगा क्योंकि कोई भी त्रुटि mageCoreErrorHandlerप्रोग्राम या प्रोग्राम द्वारा नहीं डाली जाएगी exit

पहले Magento की मुख्य त्रुटि अप्राप्य त्रुटियों के लिए हैंडलर app/code/core/Mage/Core/functions.php

/**
 * Custom error handler
 *
 * @param integer $errno
 * @param string $errstr
 * @param string $errfile
 * @param integer $errline
 */
function mageCoreErrorHandler($errno, $errstr, $errfile, $errline){
    /**
     * Some internal logic here for building the error message
     */

    $errorMessage .= ": {$errstr}  in {$errfile} on line {$errline}";
    if (Mage::getIsDeveloperMode()) {
        throw new Exception($errorMessage);
    } else {
        Mage::log($errorMessage, Zend_Log::ERR);
    }
}

जैसा कि आप देख सकते हैं, डेवलपर मोड में यह कुछ उपयोगी बताएगा, यह एक त्रुटि फेंकता है। बंद होने पर यह लॉग (यदि सक्षम है) और जारी रहेगा।

सबूत

मेरे testfile.php

require 'app/Mage.php';
Mage::app('admin')->setUseSessionInUrl(false);

// Test function which expect Customer_Model_Customer
function test(Customer_Model_Customer $customer)
{
    var_dump('Do not show me because ' . get_class($customer) . ' is not a customer.');
}

// Enabled developer mode
Mage::setIsDeveloperMode(true);

// Put a var in here
$noGood = Mage::app();

// Make some context
var_dump('hello');
try {
    // Call test function with a not accepted var
    test($noGood);

    // Tell if we get here
    var_dump('And we are here!');

} catch (Exception $e) {
    var_dump('You should die, because I am doing something which I should not do');
}

परिणाम

डिवेलपरमोड सक्षम। सही परिणाम

string(5) "hello"
string(66) "You should die, because I am doing something which I should not do"

डिवेलप्मोड अक्षम, गलत परिणाम

string(5) "hello"
string(61) "Do not show me because Mage_Core_Model_App is not a customer."
string(16) "And we are here!"

तो यह अंततः त्रुटि को छोड़ देगा और कोड की अगली पंक्ति पर जारी रहेगा। शायद भी अजीब परिणामों के साथ। (as @mpw बताते हैं)

निष्कर्ष

ऐसा हो सकता है कि कोई व्यक्ति इस तरह से विकसित हो रहा है कि त्रुटियों पर किसी का ध्यान नहीं जाएगा और यह अंततः अप्रत्याशित परिणाम देगा।

पेशेवर तरीके से विकसित होने पर संभोग। त्रुटियों पर ध्यान दिया जाएगा और ध्यान दिया जाएगा । मैगेंटो में इसे रोकने का तरीका डेवलपर / परीक्षण वातावरण में हमेशा से ही विकास को सक्षम बनाता है।

IMHO को चर्चा के इस बिंदु पर कभी नहीं जाना चाहिए, जहां दूसरी बार एक चर की जाँच करना (कम से कम यह है कि मैं इसे कैसे बताऊंगा) जाने का रास्ता है। उत्पादन वातावरण पर जारी करने से पहले कोड का परीक्षण किया जाना चाहिए। यह नहीं करना चाहिए जरूरत ।

दूसरा विचार

शायद मैगेंटो को एक घातक त्रुटि के बाद रुकना चाहिए। या एक रिपोर्ट उत्पन्न करें और इसे आगंतुक को दिखाएं। इस तरह से कोड की अगली पंक्तियों को कभी भी निष्पादित नहीं किया जाएगा, और चीजों पर ध्यान दिया जाएगा।


> एक पेशेवर तरीके से विकसित होने पर मोटे। त्रुटियों पर ध्यान दिया जाएगा और ध्यान दिया जाएगा। मैगेंटो में इसे रोकने का तरीका डेवलपर / परीक्षण वातावरण में हमेशा से ही विकास को सक्षम बनाता है। ¶ मैं इस से सहमत हूँ। मेरा लक्ष्य उत्पादन मोड में Magento सम्मान भाषा नियम है। ऐसा लगता है कि शायद इसे एक कस्टम मॉड्यूल की आवश्यकता होगी। आपकी अंतर्दृष्टि के लिए धन्यवाद!
मप्र

शायद Magento दोनों मामलों में एक अपवाद फेंक देना चाहिए। उपयोगकर्ता को एक Magento त्रुटि पृष्ठ प्रस्तुत किया जाएगा और var / अपवाद में एक मिलान लॉगफ़ाइल होगा, नियमित अपवादों के समान। यहाँ महान पकड़ यह है कि कोड को बिना सूचना के निष्पादित नहीं किया जाएगा। आप फ़ंक्शन फ़ाइल को ऐप / कोड / स्थानीय में कॉपी कर सकते हैं और हमेशा एक अपवाद फेंक सकते हैं
Jeroen

1
मैंने उत्तर के रूप में इसे चिह्नित करने का निर्णय लिया है। हालांकि मुझे अभी भी लगता है कि इस तरह की त्रुटियों को मफल करना खतरनाक है, लेकिन यह संभव नहीं लगता है कि मैगेंटो अन्य समस्याओं को खोलने के बिना मैगेंटो का सम्मान करता है। देव मोड को चालू रखने के लिए अनुस्मारक भविष्य के पाठकों के लिए एक अच्छा है, और यह सबसे महत्वपूर्ण
उपाय है

2

अच्छा प्रश्न। मुझे लगता है कि यह एक सामान्य समस्या है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_Core_Model_App ( ) (संरक्षित पद्धति के माध्यम से) Mage::app()की init()विधि द्वारा पंजीकृत हो जाता है ।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 है )।

मैगेंटो के त्रुटि हैंडलर पर अन्य सभी त्रुटियां पारित की जाती हैं।

नोट: मैंने यह कोशिश नहीं की है, यह एक राइट-अप है, लेकिन मुझे पता है कि आप जिस समस्या के बारे में पूछ रहे हैं और त्रुटि हैंडलिंग विश्लेषण 1.5.1.0 के खिलाफ किया गया है और कोड विश्लेषण के माध्यम से 1.9.1.0 के खिलाफ सत्यापित किया गया है। त्रुटि हैंडलर स्टैकिंग काम करना चाहिए। मैं थोड़ा विस्तारित उदाहरण कोड जोड़ता हूं जो काम करने वाले अधिकांश हिस्सों को प्रदर्शित करता है।

मैंने अभी तक इसे एक Magento एक्सटेंशन के रूप में पैक नहीं किया है, लेकिन इसे सीधे modman के साथ आगे बढ़ाया जाना चाहिए। मैं इसे तब गीथूब पर रखूंगा।

परिशिष्ट: त्रुटि हैंडलर डेमो

निम्न कोड-उदाहरण ( ऑनलाइन डेमो ) त्रुटि संचालकों के स्टैकिंग को दर्शाता है और कैटलेबल घातक त्रुटि पर अपवाद को फेंक रहा है :

<?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

उत्कृष्ट लेखन। आपके परीक्षण के दौरान, त्रुटि हैंडलर को फिर से सेट करने से मापनीय प्रदर्शन में गिरावट आई थी?
MPw

मैंने अब तक ऐसा नहीं किया है। कोर में एक संबंधित क्षेत्र भी है जहाँ विकास मोड पर सभी चेतावनियाँ / त्रुटियाँ अपवाद में परिवर्तित हो जाती हैं (और ErrorExceptuion नहीं - लॉग भी नहीं)। यह शायद एक समझदार तरीके से इसे ठीक करने के लिए एक पैचसेट की आवश्यकता है। त्रुटि हैंडलर के लिए, कोई अच्छी प्रेषण विधि उपलब्ध नहीं है, यहाँ भी मैं किसी तरह एक निश्चित डिफ़ॉल्ट त्रुटि हैंडलर लाने के लिए पैच कोर की ओर
रुख करता हूँ

1

इसे पहले से ही डिफ़ॉल्ट PHP द्वारा जोड़कर देखा जाता है (Exception $e) फंक्शनल पैरामीटर डेफिनिशन परिभाषा में ।

आप अपवाद या अपवाद की तुलना में इस फ़ंक्शन के लिए कुछ और पास नहीं कर सकते।


mageCoreErrorHandlerफ़ंक्शन पर एक नज़र डालें । गलत परमेस द्वारा ट्रिगर की गई एक त्रुटि को गैर-डेवलपर मोड में संभाला जाएगा और दबा दिया जाएगा, और Exceptionडेवलपर मोड में फेंक दिया जाएगा ।
मप्र

पहली बार में ऐसा होने पर कुछ गंभीर रूप से गलत है। Magento को यह mageCoreErrorHandlerसुनिश्चित करना होगा कि आगंतुकों को उनके चेहरे पर एक त्रुटि नहीं मिलेगी। आप try{}catch(){}उन्हें स्वयं हड़पने के लिए खुद का निर्माण कर सकते हैं, और यदि आप उन्हें पास नहीं कर सकते हैं।
जीरन

किसी भी तरह की दमनकारी घातक त्रुटि के मामले में कोई अपवाद नहीं माना जाता है, तो क्या कोशिश / पकड़ मुझे मिलेगी?
मप्र १

1
मैं अंत में इसे प्राप्त कर रहा हूं, स्थानीय परीक्षण के बाद ... आप बहुत सही हैं, त्रुटि को दबा दिया गया है और कोड जारी रहेगा। मैं अपने उत्तर को अपडेट करूंगा और कुछ अतिरिक्त विचार
जोड़ूंगा

मैं एक नया उत्तर दूंगा अन्यथा हमारी बातचीत का कोई मतलब नहीं है
जीरो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.