PHP नेस्टेड फ़ंक्शन किसके लिए हैं?


80

जावास्क्रिप्ट में नेस्टेड फ़ंक्शन बहुत उपयोगी हैं: क्लोजर, निजी तरीके और आपके पास क्या है ..

नेस्टेड PHP फ़ंक्शन किसके लिए हैं? क्या कोई उनका उपयोग करता है और किस लिए?

यहाँ एक छोटी सी जाँच मैंने की है

<?php
function outer( $msg ) {
    function inner( $msg ) {
        echo 'inner: '.$msg.' ';
    }
    echo 'outer: '.$msg.' ';
    inner( $msg );
}

inner( 'test1' );  // Fatal error:  Call to undefined function inner()
outer( 'test2' );  // outer: test2 inner: test2
inner( 'test3' );  // inner: test3
outer( 'test4' );  // Fatal error:  Cannot redeclare inner()

1
मैं शपथ ले सकता था मैंने पढ़ा कि इसके लिए समर्थन PHP6 में गिराया जा रहा था लेकिन मैं इसे कहीं भी नहीं ढूँढ सकता।
ग्रेग

2
@ मुझे लगा कि PHP6 के लिए पूरी योजना वैसे भी हवा में थी?
जेम्स

वे बड़े कार्यों के लिए महान हैं
सॉर्ट

आप PHP में भी बंद हो गए हैं, कोई पसीना नहीं।
Gralgrathor

जवाबों:


88

मूल रूप से कोई नहीं है। मैंने हमेशा इसे पार्सर के साइड इफेक्ट के रूप में माना है।

Eran Galperin को यह सोचने में गलत समझा जाता है कि ये कार्य किसी तरह निजी हैं। उन्हें बस outer()चलाने तक अघोषित किया जाता है। वे निजी तौर पर भी नहीं हैं; वे वैश्विक दायरे को प्रदूषित करते हैं, भले ही देरी हुई हो। और कॉलबैक के रूप में, बाहरी कॉलबैक को अभी भी केवल एक बार कॉल किया जा सकता है। मैं अभी भी यह नहीं देखता कि इसे एक सरणी पर लागू करना कैसे उपयोगी है, जो बहुत संभावना है कि उपनाम एक से अधिक बार कॉल करता है।

एकमात्र 'वास्तविक दुनिया' का उदाहरण जो मैं खोद सकता था वह यह है , जो केवल एक बार चल सकता है, और क्लीनर को फिर से लिखा जा सकता है, आईएमओ।

एकमात्र ऐसा [name]_includeतरीका जिसके बारे में मैं सोच सकता हूं, वह मॉड्यूल के लिए एक विधि को कॉल करने के लिए है, जो वैश्विक अंतरिक्ष में कई नेस्टेड तरीकों को संयुक्त रूप से सेट करता है

if (!function_exists ('somefunc')) {
  function somefunc() { }
}

जाँच करता है।

PHP का OOP स्पष्ट रूप से एक बेहतर विकल्प होगा :)


9
हाँ सच में। वह क्रूरता से बुरा है।
टोनी अर्कल्स

1
महान उदाहरण लिंक। मुझे विरासत के बजाय इसे लागू करना शुरू करना चाहिए!
zanlok

defरूबी में समान घोषणाएं
user102008

1
हालांकि वे बिल्कुल निजी कार्य नहीं हैं, फिर भी उन्हें बाहरी फ़ंक्शन नहीं कहा जा सकता है, इसलिए यह उन्हें बाहरी फ़ंक्शन के साथ "संयोजन के रूप में" चलाने के लिए एक प्रकार की निर्भरता देता है ...
techexpert

2
इस व्यवहार के बिना ऑटोलॉड काम नहीं करेगा। यदि किसी फ़ंक्शन के अंदर घोषणाएँ किसी भी तरह से निजी हैं, तो आपके ऑटोलड हैंडलर द्वारा किए गए शामिल / आवश्यकता को कुछ भी नहीं करना होगा।
11

88

यदि आप PHP 5.3 का उपयोग कर रहे हैं, तो आप एक गुमनाम फ़ंक्शन के साथ अधिक Javacript- जैसा व्यवहार प्राप्त कर सकते हैं:

<?php
function outer() {
    $inner=function() {
        echo "test\n";
    };

    $inner();
}

outer();
outer();

inner(); //PHP Fatal error:  Call to undefined function inner()
$inner(); //PHP Fatal error:  Function name must be a string
?>

आउटपुट:

test
test

11
एक कार्यात्मक उत्तर के साथ वास्तव में (मूल रूप से) कार्यात्मक विषय का उत्तर देने के लिए +1, और ओओपी नहीं
पीटर होस्ट

प्रश्न लेखक को स्वीकार किए गए प्रश्न को इस पर अद्यतन करना चाहिए। यह वही है जो वास्तव में मेरे समय तक सवाल का जवाब देता है।

9

[@PierredeLESPINAY द्वारा टिप्पणी के अनुसार लिखा गया।]

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

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

<?php // Some framework module

function provide_defaults()
{
    // Make sure a critical function exists:
    if (!function_exists("tedious_plugin_callback"))
    {
        function tedious_plugin_callback()
        {
        // Complex code no plugin author ever bothers to customize... ;)
        }
    }
}

2
हालांकि, ओपी के अनुसार, नेस्टेड फंक्शन स्कोप कंटेनर फंक्शन तक सीमित नहीं है ...
पियरे डी लेसपिन

1
@PierredeLESPINAY: उफ़, बहुत सच, इशारा करने के लिए बहुत बहुत धन्यवाद! : -o मैंने उसी हिसाब से उत्तर को अपडेट (फिर से लिखा) किया। (यानी यह अभी भी एक बहुत ही उपयोगी विशेषता है, लेकिन फिर एक पूरी तरह से अलग कारण के लिए।)
एसजेड।

7

फ़ंक्शंस के भीतर परिभाषित फ़ंक्शंस, मैं सशर्त रूप से परिभाषित फ़ंक्शंस के लिए बहुत उपयोग नहीं देख सकता। उदाहरण के लिए:

if ($language == 'en') {
  function cmp($a, $b) { /* sort by English word order */ }
} else if ($language == 'de') {
  function cmp($a, $b) { /* sort by German word order; yes it's different */ }
} // etc

और फिर आपके सभी कोड को यूआरओटी () कॉल जैसी चीजों में 'सीएमपी' फ़ंक्शन का उपयोग करना होगा ताकि आप अपने कोड पर सभी भाषा की जाँच न करें। अब मैंने ऐसा नहीं किया है लेकिन मैं इसे करने के लिए तर्क देख सकता हूं।


1
दिन में वापस, हम इस स्वयं को संशोधित कोड कहते हैं। एक महान उपकरण, लेकिन दुरुपयोग के लिए गोटो जितना खतरनाक ...
किलरॉय

2
बुरा विचार। बेहतर: OO का उपयोग करें और स्क्रिप्टिंग इंजन विवरण में हैक न करें।
zanlok

1
अवगत रहें - यह चर असाइन किए गए अनाम कार्यों को अनसेट करना संभव है।
BF

4

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

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

सामान्यतया, जावास्क्रिप्ट के रूप में मानक का उपयोग करके अन्य सी आधारित प्रोग्रामिंग भाषाओं का मूल्यांकन करना एक बुरा विचार है। PHP, Python, Perl, C, C ++ और Java की तुलना में जावास्क्रिप्ट निश्चित रूप से अपना जानवर है। बेशक, बहुत सारी सामान्य समानताएं हैं, लेकिन नीटी, किरकिरा विवरण (संदर्भ जावास्क्रिप्ट: निश्चित गाइड, 6 वें संस्करण, अध्याय 1-12 ), जब ध्यान दिया जाता है, तो कोर जावास्क्रिप्ट को अद्वितीय, सुंदर, अलग, सरल और एक ही समय में सभी जटिल। वह मेरा दो सेंट है।

बस स्पष्ट होना, मैं नहीं कह रहा हूँ नेस्टेड कार्य निजी हैं। बस उस घोंसले के शिकार से अव्यवस्था से बचने में मदद मिल सकती है जब कुछ तुच्छ को संशोधित करने की आवश्यकता होती है (और केवल मूल कार्य द्वारा आवश्यक है)।


2

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

एक एकल विधि के एक्सप्रेस उपयोग के लिए एक नई विधि बनाने में बहुत कम बिंदु है। मेरे लिए यह अनाड़ी कोड है और सॉर्ट-ओओ का बिंदु नहीं है। यदि आप उस फ़ंक्शन को कभी भी कहीं और कॉल नहीं करने जा रहे हैं, तो उसे घोंसला दें।


1
आप पैसे पर बहुत अधिक हैं, लेकिन मुझे लगता है कि array_filter (), array_map (), preg_replace_callback (), uasort (), और जैसे के लिए कॉलबैक फ़ंक्शन की घोषणा करते समय एक बेहतर उदाहरण होगा। मैं इन कार्यों का उपयोग उचित मात्रा में करता हूं, और शायद ही कभी मुझे कॉलबैक की आवश्यकता होती है जिसे मैं ओओपी पद्धति के बाहर घोषित कर रहा हूं जिसे मैं इसे कह रहा हूं, इसलिए कॉलबैक फ़ंक्शन के साथ वैश्विक या यहां तक ​​कि क्लास नेमस्पेस को प्रदूषित होने से बचाने के लिए बहुत क्लीनर लगता है। । और मैं अंततः PHP 5.3 के साथ ऐसा कर सकता हूं (जैसा कि user614643 के उत्तर में समझाया गया है)!
डेरेक

1

Webservice कॉलिंग में हमने पाया कि यह एक बहुत कम ओवरहेड (मेमोरी और गति) है, एक नेस्टेड फैशन में, विभिन्न कार्यों के पुस्तकालयों से भरे व्यक्तिगत कार्यों सहित। ठेठ कॉल स्टैक 5-10 कॉल के बीच हो सकता है गहरी केवल एक दर्जन 1-2kb फ़ाइलों को जोड़ने की आवश्यकता होती है गतिशील रूप से मेगाबाइट सहित बेहतर था। यह केवल एक छोटा सा उपयोग फ़ंक्शन रैपिंग बनाने के लिए आवश्यक था। शामिल फ़ंक्शन कॉल स्टैक के ऊपर फ़ंक्शन के भीतर नेस्टेड हो जाते हैं। यह उन 100 कार्यों से भरी कक्षाओं के विपरीत है, जिन पर हर वेबसर्विस कॉल की आवश्यकता नहीं थी, लेकिन इसमें php की इनबिल्ट लेज़ी लोडिंग सुविधाओं का भी उपयोग किया जा सकता था।


1

यदि आप php 7 में हैं, तो इसे देखें: यह कार्यान्वयन आपको नेस्टेड फ़ंक्शन के बारे में एक स्पष्ट विचार देगा। मान लीजिए कि हमारे पास तीन फ़ंक्शन (भी), बू () और चिड़ियाघर ()) फंक्शन फू में निहित हैं। बू () और चिड़ियाघर () में एक ही नामांकित फ़ंक्शन xoo () है। अब इस कोड में मैंने नेस्टेड फ़ंक्शन के नियमों को स्पष्ट रूप से टिप्पणी की है।

   function foo(){
        echo 'foo() is called'.'<br>';
        function too(){
            echo 'foo()->too() is called'.'<br>';
        }
        function boo(){
            echo 'foo()->boo() is called'.'<br>';
            function xoo(){
                echo 'foo()->boo()->xoo() is called'.'<br>';
            }
            function moo(){
                echo 'foo()->boo()->moo() is called'.'<br>';
            }
        }
        function zoo(){
            echo 'foo()->zoo() is called'.'<br>';
            function xoo(){     //same name as used in boo()->xoo();
                echo 'zoo()->xoo() is called'.'<br>';
            }
        #we can use same name for nested function more than once 
        #but we can not call more than one of the parent function
        }
    }

/****************************************************************
 * TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
 ****************************************************************/
    #xoo();//error: as we have to declare foo() first as xoo() is nested in foo()

    function test1(){
        echo '<b>test1:</b><br>';
        foo(); //call foo()
        too();
        boo();
        too(); // we can can a function twice
        moo(); // moo() can be called as we have already called boo() and foo()
        xoo(); // xoo() can be called as we have already called boo() and foo()
        #zoo(); re-declaration error
        //we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
    }

    function test2(){
        echo '<b>test2:</b><br>';
        foo(); //call foo()
        too();
        #moo(); 
        //we can not call moo() as the parent function boo() is not yet called
        zoo(); 
        xoo();
        #boo(); re-declaration error
        //we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()

    }

अब अगर हम test1 () कहते हैं तो आउटपुट यह होगा:

test1:
foo() is called
foo()->too() is called
foo()->boo() is called
foo()->too() is called
foo()->boo()->moo() is called
foo()->boo()->xoo() is called

अगर हम test2 () कहते हैं तो आउटपुट यह होगा:

test2:
foo() is called
foo()->too() is called
foo()->zoo() is called
zoo()->xoo() is called

लेकिन हम पुन: घोषणा त्रुटि से बचने के लिए एक ही समय में text1 () और test2 () दोनों को कॉल नहीं कर सकते


यह पढ़ने और पचाने में आसान होगा यदि फ़ंक्शन नाम, मनमाने ढंग से, तुकबंदी करने वाले, समान नाम वाले नामों के बजाय प्रत्येक फ़ंक्शन की कुछ अनूठी विशेषता को दर्शाते हैं। यह भ्रामक है और मुश्किल है। उन नामों का चयन करना जो हमें इस बात पर नज़र रखने में मदद करते हैं कि प्रत्येक कहाँ स्थित है, इस उपयोगकर्ता को अनुकूल बनाएगा और पढ़ने और समझने के लिए आवश्यक संज्ञानात्मक भार को कम करेगा। मेरे पास इस पद के माध्यम से इसे बनाने के लिए समय, या सजा की इच्छा नहीं है, हालांकि आपके पास शायद वहां एक महान बिंदु छिपा है, मुझे संदेह है कि कुछ लोग इसे खुदाई करने के लिए चारों ओर चिपक जाएंगे। SO पढ़ना एक शोध परियोजना नहीं है। KISS
SherylHohman

0

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन fwiw मैं नेस्टेड फ़ंक्शंस का उपयोग एक पुनरावर्ती कॉल के लिए एक साफ और सुव्यवस्थित दृष्टिकोण देने के लिए करता हूं, जब मुझे केवल स्थानीय रूप से कार्यक्षमता की आवश्यकता होती है - उदाहरण के लिए पदानुक्रमित ऑब्जेक्ट आदि के निर्माण के लिए (जाहिर है कि आपको माता-पिता के कार्य से सावधान रहना होगा एक बार कहा जाता है):

function main() {
    // Some code

    function addChildren ($parentVar) {
        // Do something
        if ($needsGrandChildren) addChildren ($childVar);
    }
    addChildren ($mainVar); // This call must be below nested func

    // Some more code
}

उदाहरण के लिए JS के साथ तुलना में php में ध्यान देने वाली बात यह है कि नेस्टेड फंक्शन के लिए कॉल करने की आवश्यकता है, यानी नीचे, फ़ंक्शन डिक्लेरेशन (जेएस के साथ फंक्शन कॉल पैरेंट फ़ंक्शन के भीतर कहीं भी हो सकता है)


0

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


-1

मेमोइज़ेशन में नेस्टेड फ़ंक्शंस उपयोगी हैं (प्रदर्शन को बेहतर बनाने के लिए फ़ंक्शन परिणाम कैशिंग)।

<?php
function foo($arg1, $arg2) {
    $cacheKey = "foo($arg1, $arg2)";
    if (! getCachedValue($cacheKey)) {
        function _foo($arg1, $arg2) {
            // whatever
            return $result;
        }
        $result = _foo($arg1, $arg2);
        setCachedValue($cacheKey, $result);
    }
    return getCachedValue($cacheKey);
}
?>

3
मुझे यह विचार प्रिंसिपल में पसंद है, हालांकि, मुझे नहीं लगता कि यह उन कार्यों पर काम करेगा जो तर्कों को स्वीकार करते हैं और आप इन आर्गनों के आधार पर कैशिंग कर रहे हैं। जब फ़ंक्शन को 2 बार कहा जाता है, तो अलग-अलग आर्गों के साथ , परिणाम को कैश नहीं किया गया है और आप इसे फिर से करने का प्रयास _foo()करेंगे जिसके परिणामस्वरूप एक घातक त्रुटि होगी।
MrWhite

-1

नेस्टेड फ़ंक्शन उपयोगी हैं यदि आप चाहते हैं कि नेस्टेड फ़ंक्शन एक वैरिएबल का उपयोग करें जो कि पैरेंट फ़ंक्शन के भीतर घोषित किया गया था।

<?php
ParentFunc();
function ParentFunc()
{
  $var = 5;
  function NestedFunc()
  {
    global $var;
    $var = $var + 5;
    return $var;
  };
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
}
?>

2
इस तरह से आपको कभी भी ऐसा नहीं करना चाहिए।
डेनिस वी

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