PHP में एक चर के अस्तित्व के लिए परीक्षण करने का सबसे अच्छा तरीका; isset () स्पष्ट रूप से टूट गया है


187

से isset()डॉक्स :

isset() will return FALSE if testing a variable that has been set to NULL.

मूल रूप से, isset()इस बात की जांच नहीं करता है कि चर बिल्कुल सेट है या नहीं, लेकिन यह किसी भी चीज़ पर सेट है या नहीं NULL

यह देखते हुए, वास्तव में एक चर के अस्तित्व के लिए सबसे अच्छा तरीका क्या है? मैंने कुछ इस तरह की कोशिश की:

if(isset($v) || @is_null($v))

( @जब $vसेट नहीं किया जाता है तो चेतावनी से बचने के लिए आवश्यक है ) लेकिन is_null()इसके समान समस्या है isset(): यह TRUEपरेशान चर पर लौटता है ! यह भी प्रतीत होता है कि:

@($v === NULL)

ठीक वैसे ही काम करता है @is_null($v), इसलिए वह भी बाहर है।

हम PHP में एक चर के अस्तित्व के लिए मज़बूती से जाँच करने के लिए कैसे माना जाता है?


संपादित करें: स्पष्ट रूप से सेट किए गए चर के बीच PHP में अंतर है, और चर जो NULLनिम्न पर सेट हैं :

<?php
$a = array('b' => NULL);
var_dump($a);

PHP दिखाता है कि $a['b']मौजूद है, और इसका एक NULLमूल्य है। यदि आप जोड़ते हैं:

var_dump(isset($a['b']));
var_dump(isset($a['c']));

आप उस अस्पष्टता को देख सकते हैं जो मैं isset()फ़ंक्शन के बारे में बात कर रहा हूं । यहाँ इन तीनों का आउटपुट दिया गया है var_dump()s:

array(1) {
  ["b"]=>
  NULL
}
bool(false)
bool(false)

आगे संपादित करें: दो चीजें।

एक, उपयोग का मामला। एक एरे को SQL UPDATEस्टेटमेंट के डेटा में बदल दिया जाता है , जहाँ एरे की कुंजियाँ टेबल के कॉलम हैं, और एरे के मान प्रत्येक कॉलम पर लागू होने वाले मान हैं। तालिका के किसी भी स्तंभ में एक NULLमान रखा जा सकता है , NULLजो सरणी में एक मान पारित करके संकेतित है । आप की जरूरत है एक सरणी कुंजी मौजूदा नहीं के बीच अंतर करने के लिए एक रास्ता है, और एक सरणी के मान पर सेट किया जा रहा NULL; कॉलम के मूल्य को अपडेट नहीं करने और कॉलम के मूल्य को अपडेट करने के बीच अंतर है NULL

दूसरा, ज़ोर्डचे का जवाब , array_key_exists()मेरे उपरोक्त उपयोग के मामले और किसी भी वैश्विक चर के लिए, सही ढंग से काम करता है:

<?php
$a = NULL;
var_dump(array_key_exists('a', $GLOBALS));
var_dump(array_key_exists('b', $GLOBALS));

आउटपुट:

bool(true)
bool(false)

चूंकि यह ठीक से हर जगह के बारे में संभालता है, मैं देख सकता हूं कि चर के बीच कोई अस्पष्टता है जो मौजूद नहीं है और जो चर सेट हैं NULL, मैं array_key_exists()PHP में आधिकारिक सबसे आसान तरीका कह रहा हूं जो वास्तव में एक चर के अस्तित्व की जांच करता है

(केवल अन्य मामला जो मैं सोच सकता हूं कि यह वर्ग के गुणों के लिए है, जिसके लिए वहाँ है property_exists(), जो अपने डॉक्स के अनुसार , इसी तरह से काम करता array_key_exists()है कि यह ठीक से सेट नहीं होने और सेट होने के बीच अंतर करता है NULL।)


आप जाँच नहीं कर सकते - लेकिन आपको इसकी आवश्यकता क्यों है?
बहुत ज्यादा php

12
NULL का PHP में एक बहुत ही विशिष्ट अर्थ है, और यह एक पूरी तरह से अलग अवधारणा है कि एक चर सेट किया गया है या नहीं।
चाजोमेटिकस

33
अशक्त और nonexistent के बीच अंतर करने के कारण हैं । उदाहरण के लिए, आप डेटाबेस तालिका में एक पंक्ति का प्रतिनिधित्व करने के लिए एक ऑब्जेक्ट का निर्माण कर रहे हैं। पंक्ति के प्रत्येक कॉलम के लिए, आप एक निजी चर बनाते हैं, जो केवल ऑब्जेक्ट के गेटर विधि के माध्यम से सुलभ होता है। मान लें कि एक स्तंभ मान शून्य है। अब उस गेटटर विधि को कैसे पता चलता है कि क्या तालिका में ऐसा कोई स्तंभ नहीं है, या क्या इस ऑब्जेक्ट का केवल एक शून्य मान है? सौभाग्य से, मेरे मामले में, निजी चर वास्तव में एक निजी सरणी में एक प्रविष्टि है, इसलिए मैं array_key_exists का उपयोग कर सकता हूं, लेकिन यह एक वास्तविक समस्या है।
नाथन लॉन्ग

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

2
@chazomaticus लेकिन चर और सरणी तत्व मौलिक रूप से अलग-अलग चीजें हैं ; सिर्फ इसलिए कि आप उनके साथ कुछ समान काम कर सकते हैं इसका मतलब यह नहीं है कि वे 100% विनिमेय होने चाहिए। यहां "PHP भाषा में असंगतता" नहीं है, बस कुछ ऐसा है जो आपको पसंद / समझने के लिए नहीं होता है। के रूप में register_globals, मैं अभी भी एक ऐसी स्थिति के बारे में सोचने के लिए संघर्ष कर रहा हूं, जहां भी इस तरह के अंतर की आवश्यकता होगी, क्योंकि HTTP अनुरोध से पंजीकृत कुछ भी हमेशा एक स्ट्रिंग होगा, नहीं null
IMSoP

जवाबों:


97

यदि आप जिस चर की जाँच कर रहे हैं वह वैश्विक दायरे में होगा जो आप कर सकते हैं:

array_key_exists('v', $GLOBALS) 

3
आह हा! अब आप बात कर रहे हैं '! आप ऐसा कैसे कहेंगे, वर्गीय गुणों के लिए?
चाजोमेटिकस

22
भिन्नता के रूप में, यदि चेक को स्थानीय स्कोप वैरिएबल के लिए भी काम करने की आवश्यकता होती है, $defined_vars = get_defined_vars();तो इसके माध्यम से परीक्षण कर सकते हैं array_key_exists('v', $defined_vars);
हेनरिक ओपल

1
इसमें कुछ समय मेरे लिए बदसूरत दिखता है, लेकिन इस मामले में जहां आप वास्तव में एक सरणी तत्व जाँच कर रहे हैं, यह बहुत अधिक समझ में आता है: isset($foo[$bar])हो जाता हैarray_key_exists($bar, $foo)
Arild

property_existsइसके अलावा आशाजनक लगता है:> संपत्ति_एक्सिस्टर्स () फ़ंक्शन उन गुणों का पता नहीं लगा सकता है जो __get जादू पद्धति का उपयोग करके जादुई रूप से सुलभ हैं।
एलेक्स फेयर

@alexw वेरिएबल्स "__get के माध्यम से" वास्तव में मौजूद नहीं है। __get मनमाने ढंग से कोड है जो बिना किसी चर के लिए एक कमबैक के रूप में उपयोग किया जाता है, जो किसी भी प्रासंगिक डेटा को कभी भी संग्रहीत नहीं किया गया था, चाहे जो भी चाहे वापस कर सकता है।
ब्रिलियनड

46

विभिन्न चर्चाओं और उत्तरों का अवलोकन करने का प्रयास:

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

वास्तविक उपयोग के मामले (समाधान के साथ)

1. सरणी कुंजी

सरणियों के साथ चर के संग्रह की तरह व्यवहार किया जा सकता है, unsetऔर issetउन्हें इलाज के रूप में यद्यपि वे थे। हालाँकि, चूंकि वे इसकी गणना, गणना आदि कर सकते हैं, इसलिए एक लापता मूल्य वह नहीं है जिसका मूल्य है null

इस मामले में जवाब, के बजाय का उपयोग array_key_exists()करना हैisset()

चूँकि यह फ़ंक्शन तर्क के रूप में जांचने के लिए सरणी लेता है, अगर सरणी स्वयं मौजूद नहीं है, तो PHP अभी भी "नोटिस" उठाएगी। कुछ मामलों में, यह वैध रूप से तर्क दिया जा सकता है कि प्रत्येक आयाम को पहले शुरू किया जाना चाहिए था, इसलिए नोटिस अपना काम कर रहा है। अन्य मामलों के लिए, एक "पुनरावर्ती" array_key_existsफ़ंक्शन, जिसने बदले में सरणी के प्रत्येक आयाम की जांच की, इससे बचा जाएगा, लेकिन मूल रूप से एक ही होगा @array_key_exists। यह nullमूल्यों के संचालन के लिए कुछ हद तक स्पर्शरेखा भी है ।

2. वस्तु गुण

"ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग" के पारंपरिक सिद्धांत में, एन्कैप्सुलेशन और बहुरूपता वस्तुओं के प्रमुख गुण हैं; PHP के तरह एक वर्ग आधारित OOP कार्यान्वयन में, समझाया गुण वर्ग परिभाषा के भाग के रूप में घोषित किया जाता है, और यह देखते हुए पहुंच स्तर ( public, protected, या private)।

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

सरणी कुंजियों के साथ, ऑब्जेक्ट गुणों की जाँच के लिए एक समाधान भाषा में शामिल है, जिसे उचित रूप से पर्याप्त कहा जाता हैproperty_exists

चर्चा के साथ गैर-न्यायसंगत उपयोग के मामले

3. register_globals, और वैश्विक नामस्थान के अन्य प्रदूषण

इस register_globalsसुविधा ने वैरिएबल स्कोप में वैरिएबल जोड़े हैं जिनके नाम HTTP रिक्वेस्ट के पहलुओं (GET और POST पैरामीटर्स और कुकीज) द्वारा निर्धारित किए गए थे। यह छोटी गाड़ी और असुरक्षित कोड को जन्म दे सकता है, यही कारण है कि इसे PHP 4.2 के बाद से डिफ़ॉल्ट रूप से अक्षम कर दिया गया है , अगस्त 2000 को जारी किया गया और पूरी तरह से PHP 5.4 में जारी किया गया, मार्च 2012 को जारी किया गया । हालाँकि, यह संभव है कि कुछ सिस्टम अभी भी इस सुविधा के साथ चल रहे हैं या सक्षम हैं। globalकीवर्ड या $GLOBALSसरणी का उपयोग करके अन्य तरीकों से वैश्विक नामस्थान को "प्रदूषित" करना भी संभव है ।

सबसे पहले, register_globalsस्वयं अप्रत्याशित रूप से एक nullचर का उत्पादन करने की संभावना नहीं है , क्योंकि GET, POST और कुकी मान हमेशा स्ट्रिंग्स होंगे ( ''अभी भी साथ लौट रहे trueहैं isset), और सत्र में चर पूरी तरह से प्रोग्रामर के नियंत्रण में होना चाहिए।

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

4. get_defined_varsऔरcompact

PHP में कुछ शायद ही कभी उपयोग किए जाने वाले फ़ंक्शन, जैसे get_defined_varsऔर compact, आपको चर नामों का इलाज करने की अनुमति देते हैं जैसे कि वे एक सरणी में चाबियाँ थे। वैश्विक चर के लिए, सुपर-वैश्विक सरणी$GLOBALS समान पहुंच की अनुमति देती है, और अधिक सामान्य है। यदि कोई वैरिएबल संबंधित दायरे में परिभाषित नहीं किया गया है, तो एक्सेस के ये तरीके अलग तरह से व्यवहार करेंगे।

एक बार जब आप इन तंत्रों में से एक का उपयोग करके एक सरणी के रूप में चर के एक सेट का इलाज करने का निर्णय लेते हैं, तो आप उस पर सभी समान संचालन कर सकते हैं जैसे कि सामान्य सरणी पर। फलस्वरूप, देखें १।

कार्यात्मकता जो केवल यह अनुमान लगाने के लिए मौजूद है कि ये कार्य कैसे व्यवहार करने वाले हैं (उदाहरण के लिए "" लौटे हुए सरणी में एक महत्वपूर्ण 'फू' होगा get_defined_vars? ") अतिशयोक्तिपूर्ण है, क्योंकि आप केवल फ़ंक्शन चला सकते हैं और बिना किसी प्रभाव के पता लगा सकते हैं।

4 ए। चर चर ( $$foo)

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

एक चर नाम, मौलिक रूप से, प्रोग्रामर द्वारा एक मान को दिया गया लेबल है; यदि आप इसे रन-टाइम पर निर्धारित कर रहे हैं, तो यह वास्तव में एक लेबल नहीं है, लेकिन कुछ कुंजी-मूल्य स्टोर में एक कुंजी है। अधिक व्यावहारिक रूप से, एक सरणी का उपयोग नहीं करने से, आप गणना, पुनरावृति, आदि की क्षमता खो रहे हैं; की-वैल्यू स्टोर के बाहर "वैरिएबल" होना भी असंभव हो सकता है, क्योंकि यह ओवर-राइट हो सकता है $$foo

एक साहचर्य सरणी का उपयोग करने के लिए बदल जाने के बाद, कोड 1 समाधान के लिए उत्तरदायी होगा $foo->$property_name। समाधान 2 के लिए अप्रत्यक्ष वस्तु संपत्ति पहुंच (जैसे ) को संबोधित किया जा सकता है।

5. issetटाइप करने के लिए इतना आसान हैarray_key_exists

मुझे यकीन नहीं है कि यह वास्तव में प्रासंगिक है, लेकिन हां, PHP के फ़ंक्शन नाम कभी-कभी बहुत लंबे-घुमावदार और असंगत हो सकते हैं। जाहिर तौर पर, PHP के पूर्व-ऐतिहासिक संस्करणों ने एक हैश की के रूप में एक फ़ंक्शन नाम की लंबाई का उपयोग किया था, इसलिए रासमस ने जानबूझकर फ़ंक्शन नाम बनाए जैसे htmlspecialcharsकि उनके पास असामान्य संख्या में वर्ण होंगे ...

फिर भी, कम से कम हम जावा, एह नहीं लिख रहे हैं? ;)

6. Uninitialized चर में एक प्रकार होता है

चर मूल बातें पर मैन्युअल पृष्ठ इस बयान में शामिल हैं:

Uninitialized चर का उपयोग उस संदर्भ के आधार पर उनके प्रकार का डिफ़ॉल्ट मान होता है जिसमें वे उपयोग किए जाते हैं

मुझे यकीन नहीं है कि "अनइंस्टाल्यूटेड लेकिन ज्ञात प्रकार" के ज़ेंड इंजन में कुछ धारणा है या नहीं और यह कथन में बहुत अधिक पढ़ रहा है।

जो स्पष्ट है वह यह है कि यह उनके व्यवहार पर कोई व्यावहारिक अंतर नहीं डालता है, क्योंकि बिन पृष्ठ के लिए उस पृष्ठ पर वर्णित व्यवहार एक चर के व्यवहार के समान हैं, जिसका मूल्य है null। एक उदाहरण लेने के लिए, दोनों $aऔर $bइस कोड में पूर्णांक के रूप में खत्म हो जाएगा 42:

unset($a);
$a += 42;

$b = null;
$b += 42;

(पहले आप एक अघोषित चर के बारे में एक नोटिस उठाएंगे, आपको बेहतर कोड लिखने के प्रयास में, लेकिन इससे कोई फर्क नहीं पड़ेगा कि कोड वास्तव में कैसे चलता है।)

99. यदि कोई फ़ंक्शन चला है, तो पता लगाना

(इसे एक अंतिम रखते हुए, क्योंकि यह दूसरों की तुलना में बहुत लंबा है। शायद मैं इसे बाद में संपादित करूंगा ...)

निम्नलिखित कोड पर विचार करें:

$test_value = 'hello';
foreach ( $list_of_things as $thing ) {
    if ( some_test($thing, $test_value) ) {
        $result = some_function($thing);
    }
}
if ( isset($result) ) {
    echo 'The test passed at least once!';
}

अगर some_functionवापस लौट सकते हैं null, तो एक संभावना है कि वापस लौटते हुए echoभी नहीं पहुंच पाएंगे । प्रोग्रामर का इरादा तब पता लगाना था जब कभी सेट नहीं किया गया था, लेकिन पीएचपी उन्हें ऐसा करने की अनुमति नहीं देता है।some_testtrue$result

हालांकि, इस दृष्टिकोण के साथ अन्य समस्याएं हैं, जो बाहरी लूप जोड़ने पर स्पष्ट हो जाती हैं:

foreach ( $list_of_tests as $test_value ) {
    // something's missing here...
    foreach ( $list_of_things as $thing ) {
        if ( some_test($thing, $test_value) ) {
            $result = some_function($thing);
        }
    }
    if ( isset($result) ) {
        echo 'The test passed at least once!';
    }
}

क्योंकि $resultइसे कभी भी स्पष्ट रूप से शुरू नहीं किया गया है, यह बहुत पहले परीक्षण पास होने पर एक मूल्य पर ले जाएगा, जिससे यह बताना असंभव हो जाएगा कि बाद के परीक्षण पास हुए या नहीं। यह वास्तव में एक बहुत ही सामान्य बग है जब चर को ठीक से प्रारंभ नहीं किया जाता है।

इसे ठीक करने के लिए, हमें उस लाइन पर कुछ करने की ज़रूरत है जहाँ मैंने टिप्पणी की है कि कुछ गायब है। सबसे स्पष्ट समाधान $resultएक "टर्मिनल मान" पर सेट करना है जो some_functionकभी वापस नहीं आ सकता है; यदि यह है null, तो बाकी कोड ठीक काम करेगा। यदि टर्मिनल मान के लिए कोई प्राकृतिक उम्मीदवार नहीं है, क्योंकि some_functionएक बेहद अप्रत्याशित रिटर्न प्रकार है (जो संभवतः अपने आप में एक बुरा संकेत है), तो $foundइसके बजाय एक अतिरिक्त बूलियन मूल्य का उपयोग किया जा सकता है।

सोचा प्रयोग एक: very_nullनिरंतर

PHP सैद्धांतिक रूप से एक विशेष स्थिरांक प्रदान कर सकता है - साथ ही null- यहाँ टर्मिनल मान के रूप में उपयोग के लिए; संभवतः, इसे किसी फ़ंक्शन से वापस करना अवैध होगा, या इसे इसके लिए बाध्य किया जाएगा null, और संभवतः इसे फ़ंक्शन तर्क के रूप में पारित करने के लिए लागू होगा। यह इस विशिष्ट मामले को थोड़ा सरल बना देगा, लेकिन जैसे ही आपने कोड को फिर से फैक्टर करने का फैसला किया - उदाहरण के लिए, आंतरिक लूप को एक अलग फ़ंक्शन में डालने के लिए - यह बेकार हो जाएगा। यदि फ़ंक्शंस के बीच निरंतर पारित किया जा सकता है, तो आप गारंटी नहीं दे सकते कि some_functionइसे वापस नहीं किया जाएगा, इसलिए यह अब सार्वभौमिक टर्मिनल मान के रूप में उपयोगी नहीं होगा।

इस मामले में असंवैधानिक चर का पता लगाने के लिए तर्क उस विशेष स्थिरांक के तर्क को उबलता है: यदि आप टिप्पणी को प्रतिस्थापित करते हैं unset($result), और उस से अलग तरीके से व्यवहार $result = nullकरते हैं, तो आप उसके लिए एक "मूल्य" पेश कर रहे हैं, $resultजिसे पास नहीं किया जा सकता, और केवल विशिष्ट अंतर्निहित कार्यों द्वारा पता लगाया गया।

सोचा प्रयोग दो: असाइनमेंट काउंटर

अंतिम क्या ifपूछ रहा है , इस बारे में सोचने का एक और तरीका है "क्या कुछ भी करने के लिए एक असाइनमेंट किया गया है $result?" इसके एक विशेष मूल्य पर विचार करने के बजाय $result, आप शायद चर के बारे में "मेटाडेटा" के रूप में सोच सकते हैं , थोड़ा पर्ल के "वैरिएबल टैनिंग" की तरह। तो बजाय issetआप इसे कॉल कर सकते हैं has_been_assigned_to, और के बजाय unset, reset_assignment_state

लेकिन अगर ऐसा है, तो एक बूलियन पर क्यों रोकें? क्या होगा यदि आप जानना चाहते हैं कि परीक्षण कितनी बार पारित हुआ; आप बस अपने मेटाडेटा को एक पूर्णांक तक बढ़ा सकते हैं और है get_assignment_countऔर reset_assignment_count...

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

उम्मीद है कि स्पष्ट सवाल यह है कि PHP रनटाइम इंजन को अग्रिम में यह मान लेना चाहिए कि आप सामान्य कोड का उपयोग करके, स्पष्ट रूप से ऐसा करने के लिए छोड़ने के बजाय ऐसी चीजों पर नज़र रखना चाहते हैं।


वर्गों और संपत्तियों के बारे में, संपत्ति के सरणी होने पर दुखी प्रॉपर्टी_एक्सिस्ट () काम नहीं करता है, उदाहरण के लिए: क्लास {पब्लिक $ प्रॉपर्टी = ऐरे ()}। एक त्रुटि फेंकता है।
एंड्रयू

1
@ और मेरे लिए ठीक काम करने लगता है: 3v4l.org/TnAY5 एक संपूर्ण उदाहरण प्रदान करने के लिए देखभाल करें?
IMSoP

हाँ, यह ठीक काम करने के लिए लगता है, कुछ गलत मेरे सेटअप के साथ था। झूठे अलार्म के लिए क्षमा करें :)
एंड्रयू

20

कभी-कभी मुझे यह जानने की कोशिश में थोड़ा खो जाता है कि किसी दिए गए स्थिति में किस ऑपरेशन का उपयोग करना है। isset()केवल निर्जन या स्पष्ट रूप से अशक्त मूल्यों पर लागू होता है। अशक्त को पास करना / असाइन करना एक शानदार तरीका है, जो अपेक्षा के अनुसार तार्किक तुलनात्मक कार्यों को सुनिश्चित करता है।

फिर भी, यहाँ यह सोचना थोड़ा मुश्किल है कि विभिन्न तरीकों द्वारा विभिन्न मूल्यों का मूल्यांकन कैसे किया जाएगा इसकी तुलना एक सरल मैट्रिक्स है:

|           | ===null | is_null | isset | empty | if/else | ternary | count>0 |
| -----     | -----   | -----   | ----- | ----- | -----   | -----   | -----   |
| $a;       | true    | true    |       | true  |         |         |         |
| null      | true    | true    |       | true  |         |         |         |
| []        |         |         | true  | true  |         |         |         |
| 0         |         |         | true  | true  |         |         | true    |
| ""        |         |         | true  | true  |         |         | true    |
| 1         |         |         | true  |       | true    | true    | true    |
| -1        |         |         | true  |       | true    | true    | true    |
| " "       |         |         | true  |       | true    | true    | true    |
| "str"     |         |         | true  |       | true    | true    | true    |
| [0,1]     |         |         | true  |       | true    | true    | true    |
| new Class |         |         | true  |       | true    | true    | true    |

तालिका को फिट करने के लिए मैंने लेबल को थोड़ा संकुचित किया:

  • $a; एक घोषित लेकिन अप्रमाणित चर को संदर्भित करता है
  • पहले कॉलम में बाकी सब कुछ एक निर्दिष्ट मान को संदर्भित करता है, जैसे:
    • $a = null;
    • $a = [];
    • $a = 0;
    • ...
  • कॉलम तुलना संचालन का उल्लेख करते हैं, जैसे:
    • $a === null
    • isset($a)
    • empty($a)
    • $a ? true : false
    • ...

सभी परिणाम बूलियन होते हैं, trueमुद्रित होते हैं और falseछोड़ दिए जाते हैं।

आप परीक्षण स्वयं चला सकते हैं, इस gist की जाँच करें:
https://gist.github.com/mfdj/8165967


हो सकता है कि इस सवाल के दायरे से बाहर हो, लेकिन आप संचालन "0"की पूर्णता और स्पष्टता के लिए तालिका में जोड़ना चाह सकते हैंempty
रिक शहाफ

17

आप अशक्त चर के अस्तित्व के लिए परीक्षण करने के लिए कॉम्पैक्ट भाषा निर्माण का उपयोग कर सकते हैं। चर जो मौजूद नहीं हैं वे परिणाम में नहीं आएंगे, जबकि अशक्त मूल्य दिखाएंगे।

$x = null;
$y = 'y';

$r = compact('x', 'y', 'z');
print_r($r);

// Output:
// Array ( 
//  [x] => 
//  [y] => y 
// ) 

आपके उदाहरण के मामले में:

if (compact('v')) {
   // True if $v exists, even when null. 
   // False on var $v; without assignment and when $v does not exist.
}

निश्चित रूप से वैश्विक दायरे में चर के लिए आप array_key_exists () का उपयोग कर सकते हैं।

Btw व्यक्तिगत रूप से मैं प्लेग जैसी स्थितियों से बचता हूँ जहाँ एक वैरिएबल के बीच एक शब्दार्थक अंतर मौजूद है न कि वैरिएबल और शून्य मान रखने वाले वैरिएबल के बीच। PHP और अधिकांश अन्य भाषाएँ सिर्फ यह नहीं सोचतीं कि वहाँ है।


3
PHP नहीं करता है, लेकिन मैं कहूंगा कि अधिकांश अन्य भाषाएँ नहीं हैं। यदि कोई चर घोषित नहीं किया गया है, तो अधिकांश भाषाएं जो चर घोषित करती हैं, एक त्रुटि को फेंक देगी, लेकिन आप उन्हें सेट कर सकते हैं NULL। शब्दार्थ, NULLका अर्थ "कोई संसाधन नहीं" होना चाहिए, लेकिन एक चर को परिभाषित नहीं करना एक प्रोग्रामर त्रुटि है।
एम। मिलर

1
@Miller जरूर, लेकिन "नो रिसोर्स" के मामले में एक पथ का अनुसरण करने वाला कोड लिखना और "प्रोग्रामर एरर" के मामले में एक अलग रास्ता काफी बकवास है। यदि आप डिबगिंग के दौरान अघोषित चर का पता लगाना चाहते हैं, तो एक स्थिर विश्लेषण उपकरण का उपयोग करें, जैसे कि आप किसी भी भाषा में संभावित त्रुटियों का पता लगा सकते हैं।
IMSoP

@Miller, कूल, आपने यह भी कैसे सोचा।
पचेरियर

1
@MMiller लेकिन यह एक खंडन के रूप में काम नहीं करता है, क्योंकि उत्तर में बयान स्पष्ट रूप से "एक चर मौजूदा नहीं" के बारे में है, और आपका काउंटर-उदाहरण एक वस्तु संपत्ति / हैश कुंजी के बारे में नहीं है । इन मामलों के बीच अंतर सिर्फ आकस्मिक नहीं है।
IMSoP

1
@Miller - वास्तव में यह एक बेहतर उदाहरण है। फिर भी, सख्त भाषाओं में 20+ साल की प्रोग्रामिंग के बाद, जिन स्थितियों के बीच मुझे एक अंतर की आवश्यकता थी undefinedऔर nullवे इतने दुर्लभ हैं कि मैं इसे याद नहीं करता। IMHO, के लिए मुख्य उपयोग undefined"गैर-सख्त भाषा में प्रोग्रामर त्रुटि" है। एक सख्त भाषा में, अगर मुझे इसके लिए एक अलग राज्य की आवश्यकता है client did not state a value, तो मैं स्थिति के लिए उपयुक्त मूल्य घोषित करता हूं, और इसके लिए परीक्षण करता हूं। सबसे खराब स्थिति, एक अलग ध्वज चर जोड़ना होगा। लेकिन ऐसा शायद ही कभी के लिए होने से बेहतर है हमेशा दो अलग गैर मूल्य राज्यों से निपटने !!
टूलमेकरसेव

15

NULL को समझाते हुए, तार्किक रूप से सोचें

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

NULL को ठीक से समझो

NULL को "गैर-मौजूद मूल्य" के रूप में माना जाना चाहिए, जो NULL का अर्थ है। चर को PHP के रूप में वर्गीकृत नहीं किया जा सकता है क्योंकि यह नहीं बताया गया है कि यह किस प्रकार की इकाई है। यह अस्वस्थ नहीं हो सकता है, इसलिए PHP बस कहती है "ठीक है, यह नहीं है क्योंकि इसका कोई मतलब नहीं है और NULL मेरे कहने का तरीका है" "।

एक विवाद

चलो अब बहस करते हैं। "लेकिन NULL 0 या FALSE या '' कहने जैसा है।

गलत, 0-FALSE- '' सभी अभी भी खाली मूल्यों के रूप में वर्गीकृत किए गए हैं, लेकिन वे किसी प्रश्न के मूल्य या पूर्व-निर्धारित उत्तर के रूप में निर्दिष्ट हैं। FALSE हां या नहीं का जवाब है , '' किसी को सौंपे गए शीर्षक का उत्तर है, और 0 मात्रा या समय आदि का उत्तर है। वे कुछ प्रकार के उत्तर / परिणाम के रूप में सेट होते हैं जो उन्हें सेट होने के रूप में मान्य बनाता है।

NULL का अभी तक कोई जवाब नहीं है, इसलिए यह हमें हाँ या नहीं नहीं बताता है और यह हमें समय नहीं बताता है और यह हमें नहीं बताता है कि एक रिक्त स्ट्रिंग सबमिट की गई है। NULL को समझने में यही मूल तर्क है।

सारांश

यह समस्या के आसपास होने के लिए निराला कार्य बनाने के बारे में नहीं है, यह सिर्फ आपके मस्तिष्क को NULL को देखने के तरीके को बदल रहा है। यदि यह NULL है, तो मान लें कि यह कुछ भी सेट नहीं है। यदि आप पूर्व-परिभाषित चर हैं, तो उन्हें 0, FALSE या "" के रूप में पूर्व-परिभाषित करें कि आप उनके लिए किस प्रकार के उपयोग के आधार पर हैं।

इसे बेझिझक बोली। यह मेरे तार्किक सिर के ऊपर से है :)


5
बहुत बढ़िया जवाब। इसलिए कई बार मैं लोगों को इस बात से रूबरू कराता हूं कि वे किसी भाषा की इस विशेषता से कैसे नफरत करते हैं। लेकिन वे यह मानने लगते हैं कि "अगर यह मेरा तरीका नहीं करता है, तो यह टूट गया है।" हां, खराब डिजाइन के फैसले हैं। लेकिन बहुत करीबी दिमाग वाले डेवलपर्स भी हैं!
रात १२:४१ पर curtisdf

23
वहाँ परेशान चर और चर === अशक्त के बीच एक बड़ा अंतर है। एक का अस्तित्व नहीं है, दूसरे का मूल्य शून्य है। तर्क है कि अशक्त का कोई मतलब नहीं है बस सच नहीं हैं। अशक्त प्रकार का शून्य है। यह पूरी तरह से वैध मूल्य है और php के लिए इसे गैर-मौजूदा मूल्य के रूप में मानने का कोई कारण नहीं है, जो यह दुख की बात है। यह ठीक होगा, यदि गैर-मौजूदा चर शून्य थे और हर मौजूदा चर शून्य नहीं था और अशक्त को चर में निर्दिष्ट करना इसे परेशान करेगा। लेकिन ऐसी कई स्थितियाँ हैं, जहाँ कार्य वास्तविक मान के रूप में शून्य हो जाते हैं। फिर हम खराब हो गए हैं, क्योंकि इसके लिए परीक्षण करने का कोई खूनी तरीका नहीं है।
enrey

2
मुझे पता है कि हम php, नर्क में परिवर्तनशील अस्तित्व की जांच करने के लिए "माना नहीं" जा रहे हैं, इसकी जाँच करने का कोई वास्तविक तरीका भी नहीं है। मैं कोड लिखने वाला नहीं हूं, जो उस पर लागू होता है, क्योंकि यह php में संभव नहीं है। यह php की एक सीमा है। स्पष्ट रूप से गैर-सेट और अशक्त चर के बीच अंतर है, फिर भी php उन लोगों को अलग करने के लिए कोई रास्ता नहीं प्रदान करता है। फिर भी मेटा कार्यक्षमता का बहुत कुछ उस पर निर्भर करता है: गैर-मौजूदा संस्करण पढ़ना नोटिस का उत्पादन करता है, isset($a['x'])अगर आप xअशक्त हैं तो आपको गलत बताएगा , फिर भी यह दिखाई देगा count($a).. compactसभी सेट चर, सहित nulls, और इसी तरह से काम करेगा ।
enrey

3
यह उत्तर एक प्रमुख तरीके से त्रुटिपूर्ण है: OO प्रोग्रामिंग में, अशक्त "कोई वस्तु नहीं" का तार्किक विकल्प है। उदाहरण के लिए, अनैच्छिक परिस्थितियों में जब कोई फ़ंक्शन किसी वस्तु या किसी वस्तु को वापस कर सकता है, तो अशक्त स्पष्ट विकल्प है। तकनीकी रूप से PHP में, झूठी या बूलियन संदर्भ में गलत माना जाने वाला कोई भी मूल्य इस्तेमाल किया जा सकता है, लेकिन तब आप कुछ शब्दार्थ शुद्धता खो रहे हैं। इस प्रकार, शून्य एक वैरिएबल को शुरू करने के लिए एक पूरी तरह से उचित मूल्य है जो अंततः एक वस्तु को पकड़ना चाहिए, क्योंकि यह जो बनना है , उसके लिए प्रासंगिक है।
chazomaticus

3
जब तक PHP अपरिभाषित चर के लिए त्रुटियों को फेंकता है, लेकिन अशक्त के लिए नहीं, तब तक अंतर है। यदि अशक्त और अपरिभाषित वास्तव में एक ही अवधारणा थी, तो PHP को अशक्त / अघोषित चरों को शून्य मान लेना चाहिए और कभी भी कोई त्रुटि नहीं करनी चाहिए, लेकिन कोई भी व्यक्ति यह नहीं चाहता है कि यह एक बुरा सपना है। मूल्य शब्दार्थ के संदर्भ में अशक्त और अपरिभाषित वास्तव में भिन्न नहीं हो सकते हैं, लेकिन जब यह स्पष्ट और डीबग करने योग्य कोड लिखने की बात आती है, तो वे बहुत भिन्न होते हैं।
क्रिस मिडलटन

9

वस्तु गुण द्वारा अस्तित्व के लिए जाँच की जा सकती property_exists

एक इकाई परीक्षण से उदाहरण:

function testPropertiesExist()
{
    $sl =& $this->system_log;
    $props = array('log_id',
                   'type',
                   'message',
                   'username',
                   'ip_address',
                   'date_added');

    foreach($props as $prop) {
        $this->assertTrue(property_exists($sl, $prop),
                           "Property <{$prop}> exists");
    }
}

4

NULL का अर्थ क्या है के महान चर्चा के अतिरिक्त , विचार करें कि "चर का अस्तित्व" वास्तव में क्या है।

कई भाषाओं में, आपको इसका उपयोग करने से पहले प्रत्येक चर को स्पष्ट रूप से घोषित करना होगा ; यह इसके प्रकार को निर्धारित कर सकता है, लेकिन इससे भी महत्वपूर्ण बात यह है कि यह अपना दायरा घोषित करता है । एक चर इसके दायरे में हर जगह "मौजूद" है, और इसके बाहर कहीं भी नहीं है - ऐसा हो कि एक संपूर्ण फ़ंक्शन, या एक "ब्लॉक" हो।

इसके दायरे में, एक चर एक लेबल को कुछ अर्थ प्रदान करता है जिसे आपने, प्रोग्रामर ने चुना है। इसके दायरे के बाहर, वह लेबल निरर्थक है (चाहे आप एक अलग दायरे में एक ही लेबल का उपयोग करते हों) मूल रूप से अप्रासंगिक है।

PHP में, चर को घोषित करने की आवश्यकता नहीं है - जैसे ही आपको उनकी आवश्यकता होती है, वे जीवन में आते हैं। जब आप पहली बार किसी चर को लिखते हैं, तो PHP उस चर के लिए स्मृति में एक प्रविष्टि आवंटित करता है। यदि आप एक ऐसे चर से पढ़ते हैं जिसमें वर्तमान में कोई प्रविष्टि नहीं है, तो PHP उस चर को मान मानता है NULL

हालांकि, स्वचालित कोड गुणवत्ता डिटेक्टर आम तौर पर आपको चेतावनी देंगे यदि आप पहले "चर" के बिना एक चर का उपयोग करते हैं। सबसे पहले, यह टाइपोस का पता लगाने में मदद करता है, जैसे कि असाइन करना $thingIdलेकिन से पढ़ना $thing_id; लेकिन दूसरी बात, यह आपको उस स्कोप पर विचार करने के लिए मजबूर करता है, जिस पर वैरिएबल का अर्थ है, जैसे कि एक घोषणा होगी।

कोई भी कोड जो परवाह करता है कि क्या एक चर "मौजूद है" उस चर के दायरे का हिस्सा है - चाहे या नहीं इसे आरंभ किया गया है, एक प्रोग्रामर के रूप में आपने कोड के उस बिंदु पर उस लेबल का अर्थ दिया है। चूंकि आप इसका उपयोग कर रहे हैं, यह कुछ अर्थों में "अस्तित्व में" होना चाहिए, और यदि यह मौजूद है, तो इसका एक निहित मूल्य होना चाहिए; PHP में, जिसका निहितार्थ है null

PHP के काम करने के तरीके के कारण, कोड को लिखना संभव है जो मौजूद चर के नामस्थान को लेबल के एक दायरे के रूप में नहीं मानता है जो आपने अर्थ दिया है, लेकिन कुछ प्रकार के कुंजी-मूल्य स्टोर के रूप में। उदाहरण के लिए, आप इस तरह से कोड चला सकते हैं $var = $_GET['var_name']; $$var = $_GET['var_value'];:। सिर्फ इसलिए कि आप कर सकते हैं, इसका मतलब यह नहीं है कि यह एक अच्छा विचार है।

यह पता चला है, PHP में कुंजी-मूल्य स्टोर का प्रतिनिधित्व करने का एक बेहतर तरीका है, जिसे साहचर्य सरणियों कहा जाता है। और यद्यपि एक सरणी के मूल्यों को चर की तरह माना जा सकता है, आप सरणी पर परिचालन को एक पूरे के रूप में भी कर सकते हैं। यदि आपके पास एक सहयोगी सरणी है, तो आप परीक्षण कर सकते हैं कि क्या इसमें एक कुंजी का उपयोग किया गया है array_key_exists()

आप एक समान तरीके से वस्तुओं का उपयोग कर सकते हैं, गतिशील रूप से गुण सेट कर सकते हैं, जिस स्थिति में आप property_exists()बिल्कुल उसी तरह से उपयोग कर सकते हैं । बेशक, अगर आप एक वर्ग को परिभाषित, आप घोषणा कर सकते हैं जो गुण यह है - तुम भी बीच चयन कर सकते public, privateऔर protectedगुंजाइश।

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


1
बहुत अच्छे अंक, हालांकि सवाल का जवाब नहीं।
चाजोमेटिकस

1
स्पष्ट प्रश्न के लिए "हमें PHP में एक चर के अस्तित्व के लिए मज़बूती से कैसे जांचना चाहिए?" मेरा जवाब है "तुम नहीं हो, और यहाँ क्यों है"। यह उत्तर और महानतावादी दोनों भी निहित प्रश्न का उत्तर देते हैं "ऐसा isset()व्यवहार क्यों करता है ?"।
IMSoP

"यदि आप एक ऐसे चर से पढ़ते हैं जिसमें वर्तमान में कोई प्रविष्टि नहीं है, तो PHP उस चर को मान मानता है जिसके पास NULL है।" यह गलत है। एक अपरिभाषित चर बस अपरिभाषित है। जब आप इसे एक्सेस करने का प्रयास करते हैं, तो यह अशक्त हो सकता है, लेकिन यह अप्रासंगिक है।
ह्यूगो जिंक

@Hugoink क्या अप्रासंगिक है? किसी अपरिभाषित चर के मूल्य का कोई भी परीक्षण आपको बताएगा कि मूल्य क्या है null। यह देखने से पहले कि यह मूल्य मौजूद है या नहीं, यह दार्शनिकों के लिए एक सवाल है, लेकिन जहां तक ​​किसी भी व्यवहार के व्यवहार का संबंध है, मूल्य निरंतर है null
IMSoP

3

issetजाँचता है कि चर सेट है या नहीं, यदि हां, तो उसका मान NULL नहीं है। उत्तरार्द्ध हिस्सा (मेरी राय में) इस फ़ंक्शन के दायरे में नहीं है। यह निर्धारित करने के लिए कोई अच्छा समाधान नहीं है कि एक चर NULL है क्योंकि यह सेट नहीं है या क्योंकि यह स्पष्ट रूप से NULL पर सेट है

यहाँ एक संभव समाधान है:

$e1 = error_get_last();
$isNULL = is_null(@$x);
$e2 = error_get_last();
$isNOTSET = $e1 != $e2;
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0

अन्य वर्कअराउंड के आउटपुट की जांच करना है get_defined_vars():

$vars = get_defined_vars();
$isNOTSET = !array_key_exists("x", $vars);
$isNULL = $isNOTSET ? true : is_null($x);
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0

2

मैं NULL के बारे में आपके तर्क से सहमत नहीं हूँ , और यह कहना कि आपको NULL के बारे में अपनी मानसिकता बदलने की ज़रूरत है, बस अजीब है।

मुझे लगता है कि गड़बड़ी () सही ढंग से नहीं बनाई गई थी, इससेट () आपको बताना चाहिए कि क्या चर सेट किया गया है और इसका चर के वास्तविक मूल्य से कोई संबंध नहीं होना चाहिए।

क्या होगा यदि आप डेटाबेस से लौटाए गए मानों की जाँच कर रहे हैं और स्तंभों में से एक का NULL मान है, तो आप अभी भी जानना चाहते हैं कि क्या यह मौजूद है भले ही मान NULL हो ... nope is Trust isset ()।

वैसे ही

$a = array ('test' => 1, 'hello' => NULL);

var_dump(isset($a['test']));   // TRUE
var_dump(isset($a['foo']));    // FALSE
var_dump(isset($a['hello']));  // FALSE

isset () को इस तरह काम करने के लिए डिज़ाइन किया जाना चाहिए था:

if(isset($var) && $var===NULL){....

इस प्रकार हम इसे प्रोग्रामर के पास छोड़ देते हैं कि वह प्रकारों की जांच करे और इसे छोड़ कर इस्सेट () तक न जाए क्योंकि इसका मान नहीं है क्योंकि मूल्य NULL है - इसका सिर्फ बेवकूफ डिजाइन


आपका उदाहरण किसी चर की नहीं बल्कि एक सरणी कुंजी के अस्तित्व की जाँच कर रहा है। इसका एक समाधान मौजूद है, के रूप में array_key_exists। यदि आप एक वास्तविक चर मौजूद है, तो आपको कभी भी ऐसी स्थिति में नहीं होना चाहिए जहां आप रनटाइम पर नहीं जानते।
IMSoP

@chazomaticus ठीक है, आपको कभी भी ऐसी स्थिति में नहीं होना चाहिए जहां register_globals चालू हो, इसलिए मैं उस कथन के साथ खड़ा हूं।
IMSoP

ओह, मैं सहमत हूं। फिर भी, हर कोई नियंत्रित नहीं कर सकता है कि उनका कोड कहां तैनात है। हर स्थिति की जानकारी होना उपयोगी है, चाहे वह "चीजें" हों या न हों।
शैज़ोमैटिकस

@chazomaticus यदि आपकी समस्या है register_globals, तो आपका उत्तर परिवर्तन नहीं है isset()PHP मैनुअल उल्लेख किया गया है "यह आमतौर पर पहले वेरिएबल को इनिशियलाइज़ करने के लिए एक अच्छा प्रोग्रामिंग अभ्यास है", जो register_globalsरन-टाइम के बजाय डिज़ाइन-टाइम पर हल करता है। रन-टाइम में इससे निपटने के लिए एक फंक्शन एंट्री भी दी जाती है unregister_globals()
IMSoP

2

मैं इसमें एक त्वरित दो सेंट जोड़ने जा रहा हूं। यह समस्या भ्रामक होने का एक कारण यह है कि यह परिदृश्य उसी परिणाम को लौटाता है जिसमें त्रुटि रिपोर्ट पूर्ण नहीं है:

$a = null;
var_dump($a); // NULL
var_dump($b); // NULL

आप इस परिणाम से मान सकते हैं कि अंतर $a = nullऔर बिल्कुल नहीं परिभाषित करने के बीच का अंतर $bकुछ भी नहीं है।

क्रैंक त्रुटि रिपोर्ट करना:

NULL

Notice: Undefined variable: b in xxx on line n
NULL

नोट: इसने एक अपरिभाषित चर त्रुटि को फेंक दिया, लेकिन var_dumpअभी भी इसका आउटपुट मूल्य है NULL

PHP स्पष्ट रूप से एक अशक्त चर और एक अपरिभाषित चर के बीच अंतर करने की आंतरिक क्षमता रखता है। यह मुझे लगता है कि इसके लिए जाँच करने के लिए एक अंतर्निहित कार्य होना चाहिए।

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


अपरिभाषित चर पर चेतावनी प्रोग्रामर को संकेत है कि उन्होंने कोड में कुछ गलत किया है। डिबगिंग के लिए (जिसके लिए भाषा के बाहर उपकरण हैं), ऐसी स्थिति का पता लगाने के लिए कभी भी एक कार्यक्रम की आवश्यकता नहीं होनी चाहिए, क्योंकि प्रोग्रामर को हमेशा पता होना चाहिए कि वे किस चर को घोषित कर रहे हैं।
IMSoP

1

यदि मैं निम्नलिखित चलाता हूं:

echo '<?php echo $foo; ?>' | php

मुझे एक त्रुटि मिली:

PHP Notice:  Undefined variable: foo in /home/altern8/- on line 1

यदि मैं निम्नलिखित चलाता हूं:

echo '<?php if ( isset($foo) ) { echo $foo; } ?>' | php

मुझे त्रुटि नहीं मिली।

यदि मेरे पास एक चर है जिसे सेट किया जाना चाहिए, तो मैं आमतौर पर निम्नलिखित की तरह कुछ करता हूं।

$foo = isset($foo) ? $foo : null;

या

if ( ! isset($foo) ) $foo = null;

इस तरह, बाद में स्क्रिप्ट में, मैं सुरक्षित रूप से $ फू का उपयोग कर सकता हूं और यह जान सकता हूं कि यह "सेट" है, और यह अशक्त करने के लिए चूक करता है। बाद में if ( is_null($foo) ) { /* ... */ }अगर मुझे जरूरत है और मुझे पता है कि चर मौजूद है, भले ही यह अशक्त हो।

फुल इस्सेट डॉक्यूमेंटेशन जो शुरू में चिपकाया गया था, उससे थोड़ा अधिक पढ़ता है। हां, यह उस चर के लिए गलत है जो पहले सेट किया गया था, लेकिन अब शून्य है, लेकिन यह भी गलत है अगर कोई चर अभी तक (हमेशा) सेट नहीं किया गया है और किसी भी चर के लिए जिसे असेट के रूप में चिह्नित किया गया है। यह भी नोट करता है कि NULL बाइट ("\ 0") को शून्य नहीं माना जाता है और यह सही वापस आएगा।

निर्धारित करें कि क्या एक चर सेट है।

यदि कोई वैरिएबल अनसेट () के साथ है, तो वह सेट नहीं किया जाएगा। isset () FALSE लौटाएगा यदि NULL के लिए सेट किए गए चर का परीक्षण किया जाए। यह भी ध्यान दें कि एक NULL बाइट ("\ 0") PHP NULL स्थिरांक के बराबर नहीं है।


उसे उस लिंक से डॉक्स मिल गए। पहले दिए गए लिंक पर विवरण अनुभाग का दूसरा वाक्य पढ़ें, यह वही है जो उसने ऊपर उद्धृत किया है।
Zoredache

यह सरल लिपियों के लिए एक बुरा अभ्यास नहीं है, लेकिन जटिल (जैसे बड़े OO) परियोजनाओं में, यह संभव हो जाता है। इसके अलावा, जैसा कि मैंने ऊपर कहा, is_null () उन वेरिएबल्स के लिए TRUE देता है जो सेट नहीं हैं, इसलिए वास्तव में ऐसा करने का कोई कारण नहीं है कि आप PHP चेतावनी से बचने के लिए क्या कह रहे हैं।
चाजोमेटिकस

1
अच्छी तरह से डिजाइन किए गए "बड़े ऊ" परियोजनाओं के लिए, यह बिल्कुल समस्या क्यों होगी? आप कभी भी एक पद्धति निकाय में $ foo लेंगे, जो इसके पहले उपयोग से पहले सेट नहीं किया जा सकता है?
ब्यू सिमेंसन

1

प्रयोग करके देखें

unset($v)

ऐसा लगता है कि केवल एक चर सेट नहीं किया गया है जब यह विशेष रूप से परेशान है ($ v)। ऐसा लगता है कि 'अस्तित्व' का आपका अर्थ PHP की परिभाषा से अलग है। NULL निश्चित रूप से विद्यमान है, यह NULL है।


मुझे नहीं पता तुम्हारा क्या मतलब है। यदि आपके पास एक सरणी है, तो एक तत्व 'ए' के ​​साथ, आपको पीएचपी में मौजूद तत्व 'बी' के लिए परेशान () तत्व 'बी' नहीं करना है, यह बस मौजूद नहीं है। उदाहरण के लिए वैश्विक चर के साथ एक ही बात, जिसे आप $ GLOBALS सरणी के तत्वों के रूप में सोच सकते हैं।
चेजोमेटिकस

1
लेकिन मैं मानता हूं कि NULL वैल्यू वाला एक वेरिएबल वास्तव में मौजूद है।
चेजोमेटिकस

0

मुझे अपने सभी वर्षों के PHP प्रोग्रामिंग में कहना है, मुझे कभी भी isset()अशक्त चर पर गलत वापसी की समस्या का सामना नहीं करना पड़ा । OTOH, मैं isset()एक अशक्त सरणी प्रविष्टि पर असफल होने के साथ समस्याओं का सामना किया है - लेकिनarray_key_exists() उस मामले में सही ढंग से काम करता है।

कुछ तुलना के लिए, आइकन स्पष्ट रूप से अप्रयुक्त चर को परिभाषित करता है क्योंकि लौटने पर &nullआप आइकन में is-null परीक्षण का उपयोग करते हैं ताकि किसी unset चर की भी जांच कर सकें। इससे चीजें आसान हो जाती हैं। दूसरी ओर, विजुअल बेसिक के पास एक चर के लिए कई राज्य हैं जिनका कोई मान नहीं है (नल, खाली, कुछ भी नहीं ...), और आपको अक्सर उनमें से एक से अधिक के लिए जांचना होगा। इसे बग्स का स्रोत माना जाता है।


0

खाली () फ़ंक्शन के लिए PHP मैनुअल के अनुसार, "यह निर्धारित करें कि क्या एक चर को खाली माना जाता है। एक चर को खाली माना जाता है, अगर आईटी ऐसा नहीं है या तो इसका मूल्य FALSE के बराबर है। खाली () एक चेतावनी उत्पन्न नहीं करता है यदि। चर मौजूद नहीं है। " (मेरा जोर।) इसका मतलब है कि खाली () फ़ंक्शन को शीर्षक प्रश्न के अनुसार, "PHP में एक चर के अस्तित्व का परीक्षण करने का सबसे अच्छा तरीका" होना चाहिए।

हालांकि, यह पर्याप्त अच्छा नहीं है, क्योंकि खाली () फ़ंक्शन को एक चर द्वारा मूर्ख बनाया जा सकता है जो मौजूद है और इसे NULL पर सेट किया गया है।

मैं अपने पहले के उत्तर को कुछ बेहतर पेश करने के लिए बाधित कर रहा हूं, क्योंकि यह मेरे मूल उत्तर की तुलना में कम बोझिल है (जो इस रुकावट का अनुसरण करता है, तुलना करने के लिए)।

  function undef($dnc) //do not care what we receive
  { $inf=ob_get_contents();             //get the content of the buffer
    ob_end_clean();                     //stop buffering outputs, and empty the buffer
    if($inf>"")                         //if test associated with the call to this function had an output
    { if(false!==strpos($inf, "Undef"); //if the word "Undefined" was part of the output
        return true;                    //tested variable is undefined
    }
    return false;                       //tested variable is not undefined
  }

एक चर अपरिभाषित है, तो यह बताने के लिए कि कोड की दो सरल लाइनें उपरोक्त फ़ंक्शन का उपयोग कर सकती हैं:

  ob_start();                           //pass all output messages (including errors) to a buffer
  if(undef($testvar===null))            //in this case the variable being tested is $testvar

आप उन दो पंक्तियों का अनुसरण कर सकते हैं जो कुछ भी उपयुक्त हों, जैसे कि यह उदाहरण:

    echo("variable is undefined");
  else
    echo("variable exists, holding some value");

मैं कॉल को फ़ंक्शन के अंदर ob_start () और ($ testvar === null) में रखना चाहता था, और बस फ़ंक्शन को वेरिएबल पास करता हूं, लेकिन यह काम नहीं करता है। यहां तक ​​कि अगर आप फ़ंक्शन के लिए चर के "पास के संदर्भ द्वारा" का उपयोग करने की कोशिश करते हैं, तो चर को परिभाषित किया गया है, और फिर फ़ंक्शन कभी भी यह पता नहीं लगा सकता है कि यह पहले अपरिभाषित था। यहां जो प्रस्तुत किया गया है, मैं जो करना चाहता था, और वास्तव में क्या काम करता है, के बीच एक समझौता है।

पूर्ववर्ती का अर्थ है कि "अपरिभाषित चर" त्रुटि संदेश में चलने से हमेशा बचने का एक और तरीका है। (यहाँ पर धारणा यह है कि इस तरह के संदेश को रोकना यह है कि आप यह देखना चाहते हैं कि कोई चर अपरिभाषित है या नहीं।

   function inst(&$v) { return; }  //receive any variable passed by reference; instantiates the undefined

अपने $ testvar को कुछ करने से पहले बस उस फ़ंक्शन को कॉल करें:

   inst($testvar);                //The function doesn't affect any value of any already-existing variable

नव-त्वरित चर का मान निश्चित रूप से अशक्त करने के लिए सेट किया गया है!

(व्‍यवधान समाप्‍त होता है)

इसलिए, कुछ अध्ययन और प्रयोग करने के बाद, यहाँ कुछ काम करने की गारंटी है:

 function myHndlr($en, $es, $ef, $el)
 { global $er;
   $er = (substr($es, 0, 18) == "Undefined variable");
   return;
 }

 $er = false;
 if(empty($testvar))
 { set_error_handler("myHndlr");
   ($testvar === null);
   restore_error_handler();
 }
 if($er)  // will be 1 (true) if the tested variable was not defined.
 { ; //do whatever you think is appropriate to the undefined variable
 }

स्पष्टीकरण: एक चर $ एर को "कोई त्रुटि नहीं" के डिफ़ॉल्ट मान के लिए प्रारंभ किया जाता है। एक "हैंडलर फ़ंक्शन" को परिभाषित किया गया है। यदि $ testvar (वह चर जिसे हम जानना चाहते हैं कि अपरिभाषित है या नहीं) प्रारंभिक खाली () फ़ंक्शन टेस्ट पास करता है, तो हम अधिक गहन परीक्षण करते हैं। हम पहले से परिभाषित हैंडलर फ़ंक्शन का उपयोग करने के लिए set_error_handler () फ़ंक्शन को कॉल करते हैं। तब हम एक साधारण पहचान-तुलना करते हैं, जिसमें $ testvar शामिल है, जो अगर UNDEFINED हो जाएगा, तो वह एक ERROR होगा। हैंडलर फ़ंक्शन त्रुटि को पकड़ता है और विशेष रूप से यह देखने के लिए परीक्षण करता है कि क्या त्रुटि का कारण यह तथ्य है कि चर अपरिभाषित है। परिणाम को त्रुटि-सूचना चर $ एर में रखा गया है, जिसे हम बाद में परीक्षण कर सकते हैं कि हम जो कुछ भी जानना चाहते हैं उसके परिणाम के रूप में सुनिश्चित करें कि क्या $ testvar परिभाषित किया गया था या नहीं। क्योंकि हमें केवल इस सीमित उद्देश्य के लिए हैंडलर फ़ंक्शन की आवश्यकता है, हम मूल त्रुटि-हैंडलिंग फ़ंक्शन को पुनर्स्थापित करते हैं। "MyHndlr" फ़ंक्शन को केवल एक बार घोषित करने की आवश्यकता है; अन्य कोड को उन जगहों पर कॉपी किया जा सकता है जो उपयुक्त हैं, $ testvar या किसी अन्य चर के लिए जिसे हम इस तरह से परीक्षण करना चाहते हैं।


1
यदि इरादा एक चेतावनी से बचने का है कि आपके चर घोषित नहीं किए गए हैं, तो समाधान आपके कोड को उन्हें ठीक से घोषित करने के लिए ठीक करना है। आपका instफ़ंक्शन मूल रूप से @त्रुटि-दमन ऑपरेटर की तरह है: "मुझे पता है कि मैं यहां कुछ गलत कर रहा हूं, लेकिन मैं बस चाहता हूं कि संदेश दूर जाए, वास्तव में किसी भी तरह से मेरे कोड के संचालन को बदले बिना"।
IMSoP

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

0

मुझे लगता है कि एकमात्र पूर्ण समाधान के साथ नोटिस की रिपोर्ट करना है

error_reporting(E_ALL); // Enables E_NOTICE

लेकिन आपको दूसरों के बीच अपरिभाषित चर, स्थिरांक, सरणी कुंजी, वर्ग गुणों द्वारा उत्पन्न सभी नोटिस को ठीक करना होगा। एक बार जब आप ऐसा कर लेते हैं, तो आपको अशक्त और घोषित नहीं चर के बीच अंतर के बारे में चिंता करने की ज़रूरत नहीं होगी, और अस्पष्टता गायब हो जाएगी।

नोटिस रिपोर्टिंग को सक्षम करना सभी स्थितियों में एक अच्छा विकल्प नहीं हो सकता है, लेकिन इसे सक्षम करने के अच्छे कारण हैं:

मुझे E_NOTICE त्रुटियों को ठीक क्यों करना चाहिए?

मेरे मामले में इसके बिना एक प्रॉजेक्ट में काम करने में एक वर्ष से अधिक था, लेकिन इसका इस्तेमाल चर घोषित करने में सावधानी बरतने के लिए किया गया था, इसलिए यह संक्रमण के लिए तेज़ था।


0

यह जानने का एकमात्र तरीका है कि क्या एक चर को वर्तमान दायरे में परिभाषित किया गया है ( $GLOBALSभरोसेमंद नहीं है) array_key_exists( 'var_name', get_defined_vars() )


1
मुझे लगता है कि कई अन्य लोगों ने पहले कहा था, या मैं गलत हूं?
Stephan Vierkant

-1

मैं एक चर के अस्तित्व की जांच करने के लिए सबसे अच्छी विधि के रूप में खाली नहीं का उपयोग करना पसंद करता हूं जो कि ए) मौजूद है, और बी) शून्य नहीं है।

if (!empty($variable)) do_something();

2
empty()यह जाँच नहीं करता है कि चर शून्य है या नहीं, यह जाँचता है कि क्या यह गलत-y है, उदाहरण के लिए ""(एक खाली स्ट्रिंग) नहीं, 0(0 एक पूर्णांक के रूप में), 0.0(0 फ्लोट के रूप में), "0"(0 स्ट्रिंग के रूप में),NULL , FALSE, array()(एक खाली सरणी) और $var;(एक चर घोषित, लेकिन बिना मूल्य के)। आप मूल्यों के साथ दो आदानों के साथ एक रूप में एक आवश्यक रेडियो क्षेत्र है कहो 0और 1। यदि आप empty()सत्यापन के लिए उपयोग करते हैं और उपयोगकर्ता 0एक का चयन करता है , तो आप अनजाने में "आवश्यक फ़ील्ड खाली नहीं हो सकता" त्रुटि कर सकते हैं। मैनुअल php.net/manual/en/function.empty.php
Halil
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.