2013-01-18 76 views
16

पीएचपी में, आप or die बुला बाहर निकलने के लिए जब आप कुछ त्रुटियों का सामना करना है, इस तरह से त्रुटियों को संभाल कर सकते हैं:PHP में, "या मर()" काम क्यों करता है, लेकिन "या वापसी" नहीं करता है?

$handle = fopen($location, "r") or die("Couldn't get handle"); 

का उपयोग die() एक शानदार तरीका त्रुटियों को संभालने के लिए नहीं है। मैं इसके बजाय एक त्रुटि कोड वापस करूँगा ताकि पैरेंट फ़ंक्शन तय कर सके कि स्क्रिप्ट को अपमानजनक रूप से समाप्त करने और उपयोगकर्ता को त्रुटि प्रदर्शित करने के बजाय क्या करना है।

हालांकि, पीएचपी एक त्रुटि से पता चलता है जब मैं, or return साथ or die बदलने का प्रयास इस तरह:

$handle = fopen($location, "r") or return 0; 

क्यों or die() काम, लेकिन नहीं or return 0 करता है?

उत्तर

21

मैं इस प्रश्न पूछने के लिए आपको धन्यवाद देना चाहता हूं, क्योंकि मुझे नहीं पता था कि आप PHP में or return नहीं कर पाए। जब मैंने इसका परीक्षण किया तो मैं आश्चर्यचकित था। इस सवाल ने मुझे कुछ शोध करने और PHP के आंतरिक में खेलने के लिए एक अच्छा बहाना दिया, जो वास्तव में काफी मजेदार था। हालांकि, मैं PHP के आंतरिक पर एक विशेषज्ञ नहीं हूं, इसलिए निम्नलिखित PHP इंटरनल के बारे में एक आम आदमी का विचार है, हालांकि मुझे लगता है कि यह काफी सटीक है। कि के रूप में सरल - क्योंकि return एक भाषा पार्सर द्वारा "अभिव्यक्ति" नहीं माना जाता है


or return काम नहीं करता।

कीवर्ड or एक टोकन T_LOGICAL_OR कहा जाता है, और केवल अभिव्यक्ति के रूप में PHP भाषा में परिभाषित किया गया है, जहां यह this की तरह दिखता है परिभाषित किया जा रहा है:

expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } 

ब्रेसिज़ में बिट्स के बारे में चिंता मत करो - यह केवल परिभाषित करता है कि वास्तविक "या" तर्क कैसे संभाला जाता है। आपको expr T_LOGICAL_OR expr के साथ छोड़ा गया है, जो कहता है कि यह अभिव्यक्ति करने के लिए एक वैध अभिव्यक्ति है, उसके बाद T_LOGICAL_OR टोकन के बाद, एक और अभिव्यक्ति के बाद।

एक expr भी पार्सर द्वारा परिभाषित किया गया है, जैसा कि आप उम्मीद करेंगे। यह या तो r_variable हो सकता है, जिसका अर्थ यह है कि यह एक चर है जिसे आपको पढ़ने की अनुमति है, या expr_without_variable, जो यह कहने का एक शानदार तरीका है कि एक अभिव्यक्ति अन्य अभिव्यक्तियों से बनाई जा सकती है।

आप or die() कर सकते हैं क्योंकि भाषा का निर्माण die (! एक समारोह नहीं) और उसके उर्फ ​​exit दोनों टोकन T_EXIT का प्रतिनिधित्व कर रहे हैं, और T_EXIT एक वैध expr_without_variable माना जाता है, जबकि return बयान - टोकन T_RETURN - नहीं है।

अब, T_EXIT क्यों एक अभिव्यक्ति माना जाता है लेकिन T_RETURN नहीं है? ईमानदारी से, मेरे पास कोई सुराग नहीं है। हो सकता है कि यह केवल or die() निर्माण करने की अनुमति देने के लिए बनाया गया एक डिज़ाइन विकल्प था जिसे आप पूछ रहे हैं। तथ्य यह है कि इसे इतनी व्यापक रूप से उपयोग किया जाता था - कम से कम ट्यूटोरियल्स जैसी चीजों में, क्योंकि मैं बड़ी मात्रा में उत्पादन कोड से बात नहीं कर सकता - ऐसा लगता है कि यह एक जानबूझकर विकल्प हो सकता है। आपको भाषा डेवलपर्स को निश्चित रूप से जानने के लिए कहना होगा।


उन सभी के साथ, इससे कोई फर्क नहीं पड़ता। जबकि or die() निर्माण कुछ साल पहले ट्यूटोरियल्स (ऊपर देखें) में सर्वव्यापी लग रहा था, यह वास्तव में अनुशंसित नहीं है, क्योंकि यह "चालाक कोड" का एक उदाहरण है। or die() अपनी खुद की एक निर्माण नहीं है, बल्कि यह एक चाल है जो का उपयोग करता है - कुछ लोग कह सकते गाली - or ऑपरेटर के दो दुष्प्रभाव:

  • यह ऑपरेटर पूर्वता सूची में बहुत कम है, जिसका अर्थ है व्यावहारिक रूप से हर दूसरे अभिव्यक्ति से पहले यह है मूल्यांकन किया जाएगा
  • यह है एक छोटी-सर्किटिंग ऑपरेटर, जिसका अर्थ है कि दूसरे संकार्य (or के बाद बिट) के बाद से अगर एक संकार्य TRUE है निष्पादित नहीं है, तो पहले संकार्य रिटर्न TRUE, or अभिव्यक्ति में, तो वे दोनों हैं।

कुछ लोग इस प्रकार की चालबाजी को प्रतिकूल मानते हैं, क्योंकि प्रोग्रामर को पढ़ना कठिन होता है, फिर भी स्रोत कोड में कुछ स्पेस स्पेस बचाता है। चूंकि प्रोग्रामर का समय महंगा है, और डिस्क स्थान सस्ता है, आप देख सकते हैं कि लोग इसे क्यों पसंद नहीं करते हैं।

इसके बजाय, आप एक पूर्ण if बयान में अपने कोड विस्तृत करके अपने इरादे से स्पष्ट होना चाहिए:

$handle = fopen($location, "r"); 
if ($handle) { 
    // process the file 
} else { 
    return 0; 
} 

तुम भी सही if बयान में चर काम कर सकते हैं। कुछ लोगों को अभी भी इस पढ़ने योग्य नहीं लगता है, लेकिन अधिकांश लोगों (अपने आप को शामिल) असहमत:

if ($handle = fopen($location, "r")) { 
    // process the file 
} else { 
    return 0; 
} 

एक आखिरी बात: यह सम्मेलन है कि 0 वाला स्थिति कोड के रूप में वापस सफलता को इंगित करता है, तो आप शायद एक अलग मान देने के लिए चाहते हो जाएगा यह इंगित करने के लिए कि आप फ़ाइल नहीं खोल सका।

+0

यह इसके बारे में मजाकिया बात है ... [वापसी] (http://php.net/manual/en/function.return.php) एक ** भाषा निर्माण ** है और इसका उपयोग नहीं किया जा सकता है ओपी द्वारा वांछित फैशन। जबकि [मर] (http://php.net/manual/en/function.die.php) एक ** भाषा निर्माण ** भी है लेकिन अभी भी ऊपर वांछित विधि में उपयोग किया जा सकता है। जबकि मर [निकास] के लिए उपनाम है (http://php.net/manual/en/function.exit.php) एक और भाषा निर्माण जिसका उपयोग किया जा सकता है। रिटर्न इस समूह में से एक अजीब है। –

+0

@ मार्क टॉम्लिन मुझे नहीं लगता कि 'रिटर्न' यहां अजीब है। 'वापसी' एक बयान है, और इस तरह के अन्य विवरणों के साथ 'if' और' foreach' के रूप में परिभाषित किया गया है (विशेष रूप से 'unticked_statement')। यह स्पष्ट रूप से उस समूह के साथ फिट बैठता है। मुझे यकीन नहीं है कि क्यों 'निकास' को अभिव्यक्ति माना जाएगा, क्योंकि इसे एक चर को असाइन करने से फ़ंक्शन को कॉल किया जाएगा और स्क्रिप्ट को मार दिया जाएगा। इसके अलावा 'निकास' एक शून्य कार्य है, इसलिए आप चर के लिए 'NULL' असाइन करेंगे, जो सहायक नहीं है। मुझे सच में लगता है कि इसे केवल 'या मरने()' काम करने के लिए अनुमति देने की अनुमति देने के लिए एक अभिव्यक्ति माना जाता है। अजीब। – AgentConundrum

+1

+1 महान उत्तर, मेरे लिए कुछ चीजों को स्पष्ट किया :) – andr

0

मैंने भी उस पर ठोकर खाई है। टिप्पणी नीचे नीचे पर

https://bugs.php.net/bug.php?id=40712

देखो:: सभी मैं मिल सकता है यह था

यह एक बग

मैं दस्तावेज में खोज की है नहीं है और मुझे लगता है कि यह इस तथ्य के कारण है कि return 0 एक कथन है जबकि die() अनिवार्य रूप से एक अभिव्यक्ति है। आप $handle = return 0; नहीं चला सकते हैं लेकिन $handle = fun(); मान्य कोड है।

त्रुटि प्रबंधन के संबंध में मैं कस्टम कोड की सिफारिश करता हूं या कस्टम हैंडलर और ट्रिगर्स का उपयोग करता हूं। उत्तरार्द्ध उदाहरण के लिए described here हैं।

0

रिटर्न काफी विशेष है - यह फ़ंक्शन की तरह कुछ भी नहीं हो सकता है क्योंकि यह फ़ंक्शन से बाहर निकलने का टूल है। इस कल्पना कीजिए:

if(1==1) return(); // say what?? 

अगर यह इस तरह था, वापसी एक समारोह है कि एक "डबल बाहर निकलें" करता है होना करने के लिए ही नहीं, अपने स्वयं के दायरे लेकिन फोन करने वाले का छोड़ रहा है, भी होगा। इसलिए वापसी एक अभिव्यक्ति की तरह कुछ भी नहीं है, यह बस उस तरह से काम नहीं कर सकता है।

अब सिद्धांत रूप में, वापसी एक अभिव्यक्ति हो सकती है जो (कहें) झूठी और का मूल्यांकन करती है तो फ़ंक्शन छोड़ती है; शायद बाद में PHP संस्करण इसे कार्यान्वित करेगा।

वही बात गोटो पर लागू होती है जो फॉलबैक के रूप में काम करने के लिए एक आकर्षण होगी; और हां, फ़ॉलबैक आवश्यक हैं और अक्सर कोड को पठनीय बनाते हैं, इसलिए यदि कोई "चालाक कोड" (जो निश्चित रूप से एक अच्छा बिंदु है) के बारे में शिकायत करता है तो शायद पीएचपी को ऐसा करने के लिए कुछ "आधिकारिक" तरीका होना चाहिए:

connectMyDB() fallback return false; 

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

TLDR: आप बिल्कुल सही कर रहे हैं: वापसी, गोटो, तोड़ - उनमें से कोई भी काम करता है। समझने में आसान क्यों है लेकिन अभी भी परेशान है।