फोरीच के लिए अमान्य तर्क()


304

यह अक्सर डेटा को संभालने के लिए मेरे साथ होता है जो या तो एक सरणी या अशक्त चर हो सकता है और foreachइन डेटा के साथ कुछ फ़ीड कर सकता है।

$values = get_values();

foreach ($values as $value){
  ...
}

जब आप किसी ऐसे डेटा के साथ एक फ़ॉरच को खिलाते हैं जो एक सरणी नहीं है, तो आपको एक चेतावनी मिलती है:

चेतावनी: फॉर्च्यूनर के लिए आपूर्ति की गई अमान्य तर्क [...]

यह मानते हुए कि get_values()फ़ंक्शन को हमेशा किसी सरणी (बैकवर्ड संगतता, उपलब्ध स्रोत कोड, जो भी अन्य कारण हो) को वापस करने के लिए संभव नहीं है , मैं सोच रहा हूं कि इन चेतावनियों से बचने का सबसे साफ और सबसे प्रभावी तरीका क्या है:

  • $valuesसरणी के लिए कास्टिंग
  • $valuesसरणी के लिए प्रारंभिक
  • foreachएक साथ लपेटकरif
  • अन्य (कृपया सुझाव दें)

यह अत्यधिक संभव $valuesहै एक सरणी नहीं है।
भार्गव नानकेलवा

जवाबों:


509

व्यक्तिगत रूप से मुझे यह सबसे साफ लगता है - निश्चित नहीं कि यह सबसे कुशल है, मन!

if (is_array($values) || is_object($values))
{
    foreach ($values as $value)
    {
        ...
    }
}

मेरी प्राथमिकता का कारण यह है कि जब आप किसी भी तरह से शुरू करने के लिए कुछ भी नहीं मिला है तो एक खाली सरणी आवंटित नहीं करता है।


4
या काउंट () का उपयोग यह पता लगाने के लिए करें कि क्या सरणी खाली नहीं है
केमो

76
@ केमो: count()विश्वसनीय नहीं है। यदि आप count()शून्य पास करते हैं , तो यह 0. लौटाता है। यदि आप इसे एक गैर-अशक्त, गैर-सरणी तर्क पास करते हैं, तो यह 1. वापस आ जाता है। इसलिए यह count()निर्धारित करना असंभव है कि चर एक सरणी है जब चर एक खाली सरणी हो सकता है, या एक सरणी जिसमें 1 आइटम है।
एंडी शेलम

12
ध्यान दें कि कुछ वस्तुएं चलने योग्य हैं, और यह उत्तर उन लोगों के लिए नहीं है।
ब्रैड कोच

32
होना चाहिए if (is_array($values) || $values instanceof Traversable)
बॉब स्टीन

3
यह शर्म की बात है कि वह यह कहने के लिए नहीं गया था कि यह सबसे कुशल नहीं है, हालांकि: डी
गुई प्रा

116

इसके बारे में क्या खयाल है? बहुत क्लीनर और सभी एक पंक्ति में।

foreach ((array) $items as $item) {
 // ...
 }

7
यह केवल एक चीज है जो मेरे लिए काम करती है। किसी कारण से, PHP को विश्वास नहीं हुआ कि मैंने जो बहुआयामी सरणी बनाया था, वह वास्तव में सरणियों का एक सरणी था।
जस्टिन

1
यहाँ भी, यह सरणी या अशक्त मान युक्त सरणी के लिए एक बहुत अच्छा समाधान है। यदि डेटा शून्य है, तो जारी रखने के लिए फ़ॉरच लूप में एक परीक्षण जोड़ें।
छिपकली २६'१६ को ०:३

मेरी समस्या का समाधान किया। धन्यवाद!
हितेश

1
शानदार कोड, चेक के साथ $ _POST का उपयोग करके सरणी और कोई नहीं-सरणी मान के लिए, और, छोड़ दिया गया!
यान चाबोत

2
नोट: जबकि सुंदर दिखना और अमान्य फ़ॉरेस्ट चेतावनी को हल करता है, यह विधि अपरिभाषित चर चेतावनी लौटाएगी यदि चर किसी भी तरह से सेट नहीं किया गया है। उपयोग isset()या is_array()या दोनों, पूरी तरह से आपके परिदृश्य आदि पर निर्भर करता है
जेम्स

42

मैं आमतौर पर इसके समान एक निर्माण का उपयोग करता हूं:

/**
 * Determine if a variable is iterable. i.e. can be used to loop over.
 *
 * @return bool
 */
function is_iterable($var)
{
    return $var !== null 
        && (is_array($var) 
            || $var instanceof Traversable 
            || $var instanceof Iterator 
            || $var instanceof IteratorAggregate
            );
}

$values = get_values();

if (is_iterable($values))
{
    foreach ($values as $value)
    {
        // do stuff...
    }
}

ध्यान दें कि इस विशेष संस्करण का परीक्षण नहीं किया गया है, इसकी मेमोरी से सीधे SO में टाइप किया गया है।

संपादित करें: ट्रैवर्सेबल चेक को जोड़ा गया


3
सबसे बढ़िया उत्तर। सिवाय इसके कि मुझे लगता है कि आपको वास्तव में जाँच करनी चाहिए $var instanceof Traversable। देखें यहाँ । क्योंकि उदाहरण के लिए आप एक SimpleXMLElement को हटा सकते हैं , लेकिन यह Iterator या IteratorAggregate दोनों का उदाहरण नहीं है।
बॉब स्टीन

2
आप अन्य दो वर्गों को निकालने में सक्षम हो सकते हैं, @ क्रिस। वे दोनों अब ट्रैवर्सेबल का विस्तार करते हैं और ऐसा लगता है कि वे 5.0.0 में पैदा हुए हैं। हालांकि मैं एक छोटे से संदेह को महसूस कर रहा हूं कि क्या उदाहरण के लिए हमेशा एक्सटेंड किया गया था।
बॉब स्टीन

1
@ BobStein-VisiBone: हाँ (सिवाय वे इंटरफेस हैं, कक्षाएं नहीं) हालांकि; मैंने ट्रैवर्सेबल को उन लोगों के सामने रखा, न तो Iterator और न ही IteratorAggregate को कभी भी सत्यापन की आवश्यकता होगी (इस तरह वे निष्पादन को धीमा नहीं करेंगे)। मैंने उन्हें उत्तर को मूल उत्तर के करीब रखने के लिए छोड़ दिया जो मैंने दिया था और इसे स्पष्ट / पठनीय रखने के लिए।
क्रिश

2
मुझे लगता है कि is_object($var)फिर से जोड़ना उचित होगा । php.net/manual/en/language.oop5.iterations.php
मार्क फॉक्स

1
@MarkFox: स्वतंत्र महसूस करें, हालाँकि मैंने जानबूझकर इसे छोड़ दिया; मैंने इसके लिए कभी ऐसा उपयोग नहीं देखा , जिसे लागू करने Iteratorया सेवा करने से बेहतर नहीं किया गया था IteratorAggregate, लेकिन यह सिर्फ मेरी राय है और व्यक्तिपरक (मैं सार्वजनिक क्षेत्रों का उपयोग कभी नहीं करता)।
क्रिस

15

कृपया एक समाधान के रूप में कास्टिंग पर निर्भर न हों , भले ही अन्य इसे त्रुटि को रोकने के लिए एक वैध विकल्प के रूप में सुझा रहे हों, यह एक और कारण हो सकता है।

जागरूक रहें: यदि आप सरणी के एक विशिष्ट रूप की वापसी की उम्मीद करते हैं, तो यह आपको विफल कर सकता है। उसके लिए और जांच की आवश्यकता है।

उदाहरण के लिए, एक सरणी में एक बूलियन कास्टिंग (array)bool, एक खाली सरणी में परिणाम नहीं होगा , लेकिन एक तत्व के साथ एक उदाहरण के रूप में बूलियन मूल्य युक्त: [0=>0]या [0=>1]

मैंने इस समस्या को प्रस्तुत करने के लिए एक त्वरित परीक्षण लिखा । (यहां पहला टेस्ट url विफल होने की स्थिति में बैकअप टेस्ट है।)

: के लिए परीक्षण शामिल हैं null, false, true, एक class, एक arrayऔर undefined


हमेशा फ़ॉर्च में उपयोग करने से पहले अपने इनपुट का परीक्षण करें। सुझाव:

  1. त्वरित प्रकार की जाँच :$array = is_array($var) or is_object($var) ? $var : [] ;
  2. फ़ॉरच का उपयोग करने और वापसी प्रकार निर्दिष्ट करने से पहले तरीकों में सरणियों को इंगित करना टाइप करें
  3. अगर भीतर लपेटता है
  4. try{}catch(){}ब्लॉक का उपयोग करना
  5. उत्पादन रिलीज से पहले उचित कोड / परीक्षण डिजाइन करना
  6. उचित प्रपत्र के विरुद्ध किसी सरणी का परीक्षण करने के लिए आप array_key_existsकिसी विशिष्ट कुंजी का उपयोग कर सकते हैं , या किसी सरणी की गहराई का परीक्षण कर सकते हैं (जब वह एक हो तो)
  7. डुप्लिकेट कोड को कम करने के लिए अपने सहायक तरीकों को हमेशा वैश्विक नामस्थान में निकालें

8

इसे इस्तेमाल करे:

//Force array
$dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
foreach ($dataArr as $val) {
  echo $val;
}

;)


1
यह साहचर्य सरणियों के साथ अच्छी तरह से काम नहीं करेगा .. is_array विधि समग्र रूप से बेहतर है ... और आसान ...
AO_

4
$values = get_values();

foreach ((array) $values as $value){
  ...
}

समस्या हमेशा अशक्त है और कास्टिंग वास्तव में सफाई समाधान है।


3

सबसे पहले, प्रत्येक चर को आरंभीकृत किया जाना चाहिए। हमेशा।
कास्टिंग कोई विकल्प नहीं है।
अगर get_values ​​(); विभिन्न प्रकार के चर वापस कर सकते हैं, इस मूल्य की जाँच होनी चाहिए, निश्चित रूप से।


कास्टिंग एक विकल्प है - यदि आप किसी सरणी का उपयोग करते हैं $array = (array)null;तो आपको एक खाली सरणी मिलती है। बेशक यह स्मृति आवंटन की बर्बादी है ;-)
एंडी शेलम

2
+1: भावुक बिंदु से पढ़ें, मुझे परवाह नहीं है कि भाषा के बिना कर सकते हैं, चर घोषित किया जाना चाहिए और अविश्वसनीय परिणाम की जाँच होनी चाहिए । डेवलपर (डेवलपर) को रखना आवश्यक है और त्रुटि कम हो जाती है।
क्रिश

3

@ क्रिस के कोड का अधिक संक्षिप्त विस्तार

function secure_iterable($var)
{
    return is_iterable($var) ? $var : array();
}

foreach (secure_iterable($values) as $value)
{
     //do stuff...
}

खासतौर पर टेम्प्लेट कोड के अंदर उपयोग करने के लिए

<?php foreach (secure_iterable($values) as $value): ?>
    ...
<?php endforeach; ?>

2
क्या आपका मतलब नहीं है return is_iterable($var) ? $var : array($var);?
SQB

3

यदि आप php7 का उपयोग कर रहे हैं और आप केवल अपरिभाषित त्रुटियों को संभालना चाहते हैं तो यह सबसे साफ IMHO है

$array = [1,2,3,4];
foreach ( $array ?? [] as $item ) {
  echo $item;
}

2
foreach ($arr ? $arr : [] as $elem) {
    // Does something 
}

यह जाँचता है कि यह एक सरणी है या नहीं, लेकिन चर को शून्य या खाली सरणी होने पर लूप को छोड़ देता है।


1

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

यदि आप अपनी साइट को माइग्रेट नहीं कर रहे हैं और यह सिर्फ एक समस्या है जो PHP 5 को अपडेट करने की कोशिश में आया है। यह इन कुछ समस्याओं का ध्यान रखता है। एक मूर्खतापूर्ण समाधान की तरह लग सकता है, लेकिन मेरे लिए चाल चली।


1

इस नोटिस के लिए असाधारण मामला तब होता है जब आप सरणी को foreach लूप के अंदर शून्य करने के लिए सेट करते हैं

if (is_array($values))
{
    foreach ($values as $value)
    {
        $values = null;//WARNING!!!
    }
}

1

इस समाधान के बारे में कैसे:

$type = gettype($your_iteratable);
$types = array(
    'array',
    'object'
);

if (in_array($type, $types)) {
    // foreach code comes here
}

1

foreach()प्रदर्शन ट्वीट्स के लिए आपूर्ति की गई अमान्य तर्क चेतावनी । जाना /wp-content/plugins/display-tweets-php। फिर लाइन कोड 591 पर यह कोड डालें, यह पूरी तरह से चलेगा।

if (is_array($tweets)) {
    foreach ($tweets as $tweet) 
    {
        ...
    }
}

बहुत बढ़िया! यही स्वीकृत समाधान होना चाहिए। मेरे मामले में मैंने इसे जोड़ा है:if (is_array($_POST['auto'])){ // code }
जोड़ी

0

ऐसा लगता है कि पर्यावरण से भी कोई संबंध है:

मेरे पास "अमान्य तर्क आपूर्ति की गई फ़ॉरचार्ज ()" त्रुटि केवल देव वातावरण में है, लेकिन ठेस में नहीं (मैं सर्वर पर काम कर रहा हूं, लोकलहोस्ट नहीं)।

त्रुटि के बावजूद एक var_dump ने संकेत दिया कि सरणी वहां (एप्लिकेशन और देव दोनों मामलों में) अच्छी तरह से थी।

if (is_array($array))चारों ओर foreach ($array as $subarray)समस्या हल हो।

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


0

उपयोग is_array फ़ंक्शन, जब आप सरणी को foreach लूप पास करेंगे।

if (is_array($your_variable)) {
  foreach ($your_variable as $item) {
   //your code
}
}

0

यदि get_value()खाली है तो खाली सरणी को परिभाषित करने के बारे में क्या ?
मैं कम से कम तरीका नहीं सोच सकता।

$values = get_values() ?: [];

foreach ($values as $value){
  ...
}

0

मैं का एक संयोजन का उपयोग करेंगे empty, issetऔर is_arrayके रूप में

$array = ['dog', 'cat', 'lion'];

if (!empty($array) && isset($array) && is_array($array) {
    //loop
    foreach ($array as $values) {
        echo $values; 
    }
}

-3

मैं एंडी के समान ही काम करूंगा लेकिन मैं 'खाली' फ़ंक्शन का उपयोग करूंगा।

इस तरह:

if(empty($yourArray))
{echo"<p>There's nothing in the array.....</p>";}
else
{
foreach ($yourArray as $current_array_item)
  {
    //do something with the current array item here
  } 
}

3
-1, अगर $yourArray = 1;यह पुनरावृति करने की कोशिश करेगा, और आपको त्रुटि मिलेगी। empty()एक उपयुक्त परीक्षण नहीं है।
ब्रैड कोच

@ ब्रैडकोच बिल्कुल सही है। is_array () परीक्षण का एकमात्र विश्वसनीय तरीका है कि $ yourArray एक सरणी है या नहीं। विवरण के लिए अन्य उत्तर देखें क्यों is_array () पर्याप्त नहीं है - foreach iterators को भी संभाल सकता है।
cisisel
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.