क्या PHP में वैश्विक चर को बुरा अभ्यास माना जाता है? यदि हां, तो क्यों?


86
function foo () {
    global $var;
    // rest of code
}

मेरी छोटी PHP परियोजनाओं में मैं आमतौर पर प्रक्रियात्मक तरीके से जाता हूं। मेरे पास आम तौर पर एक चर होता है जिसमें सिस्टम कॉन्फ़िगरेशन होता है, और जब मैं इस चर को किसी फ़ंक्शन में एक्सेस करने के लिए मन करता है, तो मैं करता हूं global $var;

क्या यह बुरा अभ्यास है?


19
वैश्विक चर बुरे अभ्यास का एक पर्याय है
L iso̲̳̳n̲̳̳g̲̳p̲̳̳o̲̳̳k̲̳̳e̲̳̳


2
इकाई / स्वीकृति परीक्षण का प्रयास करें, और आप जल्दी से पाएंगे कि ग्लोबल्स एक समस्या क्यों हैं: जब आप एक से अधिक बार सामान करते हैं तो वे आपके कोड को अविश्वसनीय बना देते हैं।
काज़कई

जवाबों:


102

जब लोग अन्य भाषाओं में वैश्विक चर के बारे में बात करते हैं, तो इसका मतलब कुछ अलग होता है जो PHP में होता है। ऐसा इसलिए क्योंकि PHP में वैरिएबल वास्तव में वैश्विक नहीं हैं । एक सामान्य PHP प्रोग्राम का दायरा एक HTTP अनुरोध है। सत्र चर वास्तव में PHP "वैश्विक" चर की तुलना में एक व्यापक गुंजाइश है क्योंकि वे आमतौर पर कई HTTP अनुरोधों को शामिल करते हैं।

अक्सर (हमेशा?) आप preg_replace_callback()इस तरह से तरीकों में सदस्य कार्यों को कॉल कर सकते हैं :

preg_replace_callback('!pattern!', array($obj, 'method'), $str);

अधिक के लिए कॉलबैक देखें ।

मुद्दा यह है कि वस्तुओं को पीएचपी पर बोल्ट किया गया है और कुछ तरीकों से कुछ अजीबता पैदा होती है।

PHP के लिए विभिन्न भाषाओं के मानकों या निर्माणों को लागू करने के साथ अपने आप पर चिंता न करें। एक अन्य आम नुकसान हर चीज के शीर्ष पर ऑब्जेक्ट मॉडल चिपकाकर पीएचपी को शुद्ध ओओपी भाषा में बदलने की कोशिश कर रहा है।

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


8
यह ध्यान दिया जाना चाहिए कि PHP 5.3 इस में से कुछ को लैम्ब्डा फ़ंक्शन के साथ संबोधित करता है जिससे आप कॉलबैक के लिए वैश्विक दायरे में घोषित फ़ंक्शन का उपयोग करने से बच सकते हैं। बनाए रखने योग्य, पठनीय कोड सलाह के लिए +1
जोनाथन फिंगलैंड

क्या आप array ($obj, 'callbackMethod')कॉल में फ़ॉर्म के कॉलबैक का उपयोग नहीं कर सकते हैं preg_replace_callback()? (मुझे पता है, मैं इस OOP ख़तरा का शिकार हो गया हूं ...)
सकल

24
सवाल यह नहीं था कि "क्या वैश्विक चर का कभी इस्तेमाल किया जाना चाहिए?"। इसका उत्तर होगा, 'यदि आवश्यक हो तो अवसर पर निश्चित'। सवाल यह है कि क्या वे बुरे अभ्यास हैं। जवाब है 'हां, कभी-कभी'। पोस्टर्स टिनी प्रोजेक्ट के लिए, कुछ भी बुरा नहीं हो सकता है - हालांकि कई टीम के सदस्यों के साथ बड़ी परियोजनाओं के लिए और बहुत सारे चलती भागों में, वैश्विक चर का भारी उपयोग कोड को डिबग करना मुश्किल बना देगा, लगभग रिफ्लेक्टर के लिए असंभव और यहां तक ​​कि दर्द भी पढ़ें। क्या आप उन्हें कभी-कभी इस्तेमाल कर सकते हैं, यकीन है कि - क्या वे किना चूसते हैं, .. हाँ!
eddiemoya

@eddiemoya वैसे एडी ने कहा। बहुत सारे लोग बुरी प्रथाओं को सही ठहरा रहे हैं जैसे कि वैश्विक चर का उपयोग करना। आपको प्लेग की तरह उनसे बचना चाहिए। किसी भी सभ्य सॉफ्टवेयर इंजीनियरिंग की डिग्री आप में यह ड्रिल होगी ... व्याख्याता सिर्फ आपको इसके लिए नरक के बारे में नहीं बता रहे हैं ... वे दशकों के अनुभव से जानते हैं। आपको ऐसे सदस्य फ़ंक्शंस का उपयोग करना चाहिए जहाँ आपको उन मानों का उपयोग करना संभव हो,

27

वैश्विक चर अगर सावधानी से उपयोग नहीं किए जाते हैं, तो समस्याओं को खोजना मुश्किल हो सकता है। मान लीजिए कि आप एक php स्क्रिप्ट का अनुरोध करते हैं और आपको एक चेतावनी मिलती है कि आप किसी ऐसे फ़ंक्शन के इंडेक्स तक पहुंचने का प्रयास कर रहे हैं जो किसी फ़ंक्शन में मौजूद नहीं है।

यदि आप जिस ऐक्सेस को एक्सेस करने का प्रयास कर रहे हैं, वह फ़ंक्शन के लिए स्थानीय है, तो आप यह देखने के लिए फ़ंक्शन की जांच करते हैं कि क्या आपने वहाँ कोई गलती की है। यह फ़ंक्शन के इनपुट के साथ एक समस्या हो सकती है इसलिए आप उन स्थानों की जांच करें जहां फ़ंक्शन कहा जाता है।

लेकिन अगर वह सरणी वैश्विक है, तो आपको उन सभी स्थानों की जांच करने की आवश्यकता है जहां आप उस वैश्विक चर का उपयोग करते हैं, और यही नहीं, आपको यह भी पता लगाना होगा कि वैश्विक चर के उन संदर्भों को किस क्रम में एक्सेस किया गया है।

यदि आपके पास कोड के एक टुकड़े में एक वैश्विक चर है, तो उस कोड की कार्यक्षमता को अलग करना मुश्किल हो जाता है। आप कार्यक्षमता को अलग क्यों करना चाहेंगे? तो आप इसका परीक्षण कर सकते हैं और इसे फिर से उपयोग कर सकते हैं। यदि आपके पास कुछ कोड हैं जिन्हें आपको परीक्षण करने की आवश्यकता नहीं है और फिर से उपयोग करने की आवश्यकता नहीं है, तो वैश्विक चर का उपयोग करना ठीक है।


लेकिन त्रुटि अधिकांशतः यह दिखाती है कि कौन सी फाइल / लाइन स्क्रिप्ट को तोड़ रही है .. मुझे यहाँ समस्या नहीं दिख रही है
samayo

8
वह स्थान जहाँ स्क्रिप्ट टूट गई थी! = वह स्थान जहाँ गलती हुई थी।
होनरमूल्यूल

16

मैं क्लेटलस से सहमत हूं। मैं दो चीजें जोड़ूंगा:

  1. एक उपसर्ग का उपयोग करें ताकि आप तुरंत इसे वैश्विक रूप में पहचान सकें (जैसे $ g_)
  2. उन्हें एक स्थान पर घोषित करें, कोड के चारों ओर उन्हें छिड़कने न जाएं।

सबसे अच्छा संबंध है, डॉन


1
हाँ, मैं हमेशा ऐसे उपसर्गों का उपसर्ग करता हूं जिनका मैं विश्व स्तर पर उपयोग करने का इरादा रखता हूं।
KRTac

9
@KRTac लेकिन $ _testVariable को आमतौर पर एक निजी चर समझा जाता है - यह निजी चर को परिभाषित करने के लिए एक अनौपचारिक मानक है, न कि वैश्विक।
आदित्य एमपी

6
एक आम बात यह है कि सभी कैप का उपयोग करके वैश्विक संस्करण को परिभाषित करना है। उदाहरण:$DB = 'foo';
Pixline

7

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

वैश्विक चर का उपयोग करना बुरा हो सकता है, भले ही वे केवल एक कार्यक्रम के वैश्विक क्षेत्र में उपयोग किए जाते हैं, लेकिन चलो उन लोगों के बारे में मत भूलो जो केवल मज़े करना चाहते हैं और कुछ काम करना चाहते हैं

यदि वैश्विक नामस्थान में कुछ चर (<10) का उपयोग करने का मतलब है, कि केवल एक कार्यक्रम के वैश्विक क्षेत्र में उपयोग किया जाता है, तो यह हो। हाँ, हाँ, एमवीसी, निर्भरता इंजेक्शन, बाहरी कोड, ब्ला, ब्ला, ब्ला, ब्ला। लेकिन, यदि आपने अपने कोड का 99.99% नामस्थान और वर्गों में रखा है, और बाहरी कोड सैंडबॉक्स है, तो दुनिया खत्म नहीं होगी (मैं दोहराता हूं, दुनिया खत्म नहीं होगी) यदि आप एक वैश्विक चर का उपयोग करते हैं।

आमतौर पर, मैं यह नहीं कहूंगा कि वैश्विक चर का उपयोग करना है बुरा व्यवहार है । मैं कहूंगा कि एक कार्यक्रम के वैश्विक क्षेत्र के बाहर वैश्विक चर (झंडे और इस तरह) का उपयोग मुसीबत के लिए पूछ रहा है और (लंबे समय में) बीमार की सलाह दी जाती है क्योंकि आप उनके राज्यों का ट्रैक आसानी से खो सकते हैं। इसके अलावा, मैं कहूंगा कि जितना अधिक आप सीखते हैं, उतनी ही कम निर्भरता आप वैश्विक चरों पर होगी क्योंकि आपने उनके उपयोग से जुड़े बग्स पर नज़र रखने का "आनंद" अनुभव किया होगा। यह अकेले आपको उसी समस्या को हल करने के लिए एक और तरीका खोजने के लिए प्रोत्साहित करेगा। संयोग से, यह PHP लोगों को नाम स्थान और कक्षाओं (स्थिर सदस्यों, आदि ...) का उपयोग करने की दिशा में धक्का देता है।

कंप्यूटर विज्ञान का क्षेत्र विशाल है। अगर हम हर किसी को कुछ करने से डरते हैं क्योंकि हम इसे बुरा मानते हैं, तो वे वास्तव में लेबल के पीछे के तर्क को समझने में मज़ा खो देते हैं।

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


3

समाप्त SO प्रलेखन बीटा से पुनर्प्रकाशित

हम निम्नलिखित छद्म कोड के साथ इस समस्या का वर्णन कर सकते हैं

function foo() {
     global $bob;
     $bob->doSomething();
}

यहाँ आपका पहला प्रश्न स्पष्ट है

कहां $bobसे आया?

क्या आप भ्रमित हैं? अच्छा। आपने अभी-अभी जाना है कि ग्लोबल्स भ्रमित क्यों हैं और एक बुरा अभ्यास माना जाता है। यदि यह एक वास्तविक कार्यक्रम था, तो आपका अगला मज़ा सभी उदाहरणों को ट्रैक करने के लिए है $bobऔर आशा है कि आपको सही एक मिल जाएगा (यदि ऐसा होता है)$bob हर जगह उपयोग किए जाने पर जाता है)। इससे भी बदतर, अगर कोई और जाता है और परिभाषित करता है $bob(या आप भूल गए और उस चर को पुन: उपयोग किया है) तो आपका कोड टूट सकता है (उपरोक्त कोड उदाहरण में, गलत वस्तु, या बिल्कुल भी कोई वस्तु नहीं होने पर, एक घातक त्रुटि का कारण होगा)। चूँकि वस्तुतः सभी PHP प्रोग्राम include('file.php');आपके जॉब कोड को बनाए रखने के लिए कोड का उपयोग करते हैं, इस तरह से आप जितनी अधिक फाइलें जोड़ते हैं, यह उतनी ही कठिन हो जाती है।

हम ग्लोबल्स से कैसे बचें?

ग्लोबल्स से बचने का सबसे अच्छा तरीका एक दर्शन है जिसे डिपेंडेंसी इंजेक्शन कहा जाता है । यह वह जगह है जहां हम फ़ंक्शन या वर्ग में आवश्यक उपकरण पास करते हैं।

function foo(\Bar $bob) {
    $bob->doSomething();
}

यह समझना और बनाए रखना बहुत आसान है। कोई अनुमान नहीं है कि कहां $bobस्थापित किया गया था क्योंकि कॉलर यह जानने के लिए जिम्मेदार है (यह हमें गुजर रहा है जिसे हमें जानने की आवश्यकता है)। बेहतर अभी भी, हम जो कुछ भी पारित किया जा रहा है उसे प्रतिबंधित करने के लिए प्रकार की घोषणाओं का उपयोग कर सकते हैं । तो हम जानते हैं कि $bobया तो Barकक्षा का एक उदाहरण है , या बच्चे का एक उदाहरण है Bar, जिसका अर्थ है कि हम जानते हैं कि हम उस कक्षा के तरीकों का उपयोग कर सकते हैं। एक मानक ऑटोलैडर (PHP 5.3 के बाद से उपलब्ध) के साथ संयुक्त, अब हम नीचे ट्रैक कर सकते हैं जहां Barपरिभाषित किया गया है। PHP 7.0 या बाद में विस्तारित प्रकार की घोषणाएं शामिल हैं, जहां आप स्केलर प्रकार (जैसे intया string) का उपयोग कर सकते हैं ।


हर जगह $ बॉब पास करने का एक विकल्प, क्लास बार को एक सिंगलटन बनाना है, बार के भीतर ही बार के एक उदाहरण को संग्रहीत करते हुए, और ऑब्जेक्ट को तत्काल / लाने के लिए एक स्थिर विधि का उपयोग करना। फिर आप $bob = Bar::instance();जब भी जरूरत हो बस कर सकते हैं ।
स्कूटर

1
बस इस बात का ध्यान रखें कि सिंगलेट्स को एक पैटर्न-विरोधी माना जाता है । निर्भरता इंजेक्शन उन नुकसान से बचा जाता है
Machavity

2
उस पोस्ट के भीतर कुछ विवाद की स्थिति है, जिससे आप जुड़े हुए हैं (उदाहरण के लिए, स्वीकृत उत्तर के लिए शीर्ष रेटेड टिप्पणी और दूसरा सबसे उत्तोलित उत्तर दोनों स्वीकार किए गए उत्तर से दृढ़ता से असहमत हैं), जिससे मुझे यह तर्क देने में असमर्थता है कि सिंग्नों का उपयोग करना चाहिए मामले के आधार पर विचार किया जाना चाहिए, बजाए संक्षेप में हाथ से निकाले हुए।
स्कूटर

0

जैसा:

global $my_global; 
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']

बुरा व्यवहार है (Wordpress की तरह $pagenow) ... हम्मम

इस पर ध्यान दें:

$my-global = 'Transport me between functions';

PHP त्रुटि है लेकिन:

$GLOBALS['my-global'] = 'Transport me between functions';

है नहीं त्रुटि, hypens टकराव नहीं होगा के साथ "आम" उपयोगकर्ता की तरह चर घोषित, $pagenow। और UPPERCASE का उपयोग करना उपयोग में एक सुपरग्लोबल को इंगित करता है, कोड में स्पॉट करना आसान है, या फाइलों में खोज के साथ ट्रैक करें

मैं हाइफ़न का उपयोग करता हूं, अगर Im एक ही समाधान के लिए सब कुछ की कक्षाएं बनाने के लिए आलसी है, जैसे:

$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';

लेकिन अधिक व्यापक उपयोग के मामलों में, मैं सरणी के रूप में एक ग्लोबल्स का उपयोग करता हूं :

$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';

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

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