2009-10-23 17 views
7

मैं एक समारोह है कि है कि हर बार के लिए अद्वितीय हो गया है 4 वर्णों की एक प्रमुख उत्पन्न करता है। ऐसा करने के लिए, फ़ंक्शन पहले एक कुंजी उत्पन्न करता है, और तब यह देखने के लिए डेटाबेस तालिका जांचता है कि यह किसी और द्वारा उपयोग में है या नहीं।अपने अंदर एक फ़ंक्शन कैसे कॉल करें?

यदि उसका उपयोग नहीं है, यह रिटर्न कुंजी, और, यह अपने आप में एक बार फिर कहता है, लेकिन यह एक अनंत लूप करने के लिए समारोह का कारण बनता है, जो कि नहीं-नहीं। यहां पूरा कार्य है:

function key_generator($length = 4) 
{ 
    // I've subsequently left out the generating code, 
    // which is not necesarry in this case 

    $key = 'xxxx'; 

    if ($this->user_model->valid_key($key) == true) 
    { 
     return $key; 
    } 
    else 
    { 
     $this->key_generator(4); 
    } 
} 

फ़ंक्शन को फिर से कॉल करने का सही तरीका क्या है?

वैसे, मैं CodeIgniter उपयोग कर रहा हूँ, इसलिए $this

+2

यह प्रत्यावर्तन – Makach

+1

भी कहा जाता है, $ इस CodeIgniter लिए विशेष नहीं है। –

+1

मुझे लगता है कि वह सिर्फ यह बता रहा था कि यह कहां से आया था और यह कोड स्निपेट में क्यों परिभाषित नहीं किया गया है। – JAL

उत्तर

25

मैं पुन: प्रयास करें-परिदृश्यों के लिए पुनरावर्ती कार्यों का उपयोग नहीं होता (जब से तुम डॉन ' समारोह के परिणाम का पुन: उपयोग नहीं करते हैं, यह रिकर्सन का उपयोग करने के लिए व्यर्थ है) ... यह बहुत अनावश्यक ओवरहेड जोड़ता है। कुछ इस तरह है:

do { 
    $key = ...; // Generate your key here... 
} while (!$this->user_model->valid_key($key)); 

return $key; 

आप कुंजी की अधिकतम संख्या के पास हैं, तो यह, बहुत लंबे समय पाश अधिक समय लगता है तो आप अधिकतम सीमा किसी तरह डाल करने के लिए चाहते हो सकता है।

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

+0

आप सही हैं। यह सबसे अच्छा (और सबसे सरल) समाधान जैसा लगता है। धन्यवाद! –

+0

कई मामलों में आदर्श समाधान अत्यधिक लंबे लूप को रोकने के लिए बस कुछ तंत्र को रखने के लिए सावधान रहें। – Stuart

1

आप एक पाश में अपने कोड डाल दिया और कुंजी iteratively के बजाय रिकर्सिवली निर्धारित कर सकते हैं।

उदाहरण:

function key_generator($length = 4) 
{ 
    do { 
    $key = 'xxxx'; //TODO 
    if (timeOutReached()) return InvalidKey; 
    } while (!$this->user_model->valid_key($key)) 

    return $key; 
} 

पाश ही एक infinte पाश नहीं रोकता है, लेकिन एक समारोह कॉल के विपरीत, इस ढेर अंतरिक्ष खा नहीं करता है, तो आप एक ढेर अतिप्रवाह जोखिम नहीं है।

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

टिप्पणियां: यदि यह संभव है, तो अपनी खुद की मुख्य पीढ़ी की सुविधा को रोल करने के बजाय डेटाबेस की ऑटो-वृद्धि सुविधा का उपयोग करें।

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

2

लेकिन यह एक अनंत लूप करने के लिए समारोह का कारण बनता है,

आप पूरी तरह अपने पुनरावर्ती रणनीति रखना चाहते हैं आप समाप्त कर मामले को परिभाषित करने के लिए है। उदाहरण के लिए आप इस तरह एक काउंटर परिभाषित कर सकते हैं,:

function key_generator($length = 4, $limit=5) 
{ 
    if($limit === 0) { 
     throw new YourException(); 
    } 

    // I've subsequently left out the generating code, 
    // which is not necesarry in this case 

    $key = 'xxxx'; 

    if ($this->user_model->valid_key($key) == true) 
    { 
     return $key; 
    } 
    else 
    { 
     return $this->key_generator(4, ($limit-1)); 
    } 
} 

हालांकि यह भी iteratively अपने कोड करना संभव है ...

5

आपको स्वयं-कॉल का परिणाम वापस करने की आवश्यकता है, अन्यथा रिक्त होने के बाद वैध कुंजी वापस नहीं लौटाई जाएगी।

return $this->key_generator($length); 
+0

अच्छा बिंदु =) हालांकि मैं इस मामले में रिकर्सन का उपयोग करने की सिफारिश नहीं करता हूं। – Blixt

2

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

इस तरह के एक गैर-निर्धारक फैशन में लूपिंग आम तौर पर कुछ भाग के बारे में सबूत है। यह अच्छा नहीं है।

function key_generator($length = 4) 
    { 
     /* The $attempts_left clearly depends on how much trust 
      you give your key generation code combined with the key space size. */ 
     $attempts_left = pow(16, $length) * 2; 
     /* ... just guessing, in case your key base is 16, i.e. [0-9a-z] for example */ 

     do { 
      // ... key generation goes here ... 
      $key = 'xxxx'; 
     } while ($this->user_model->valid_key($key) == false && $attempts_left-- > 0); 

     if($attempts_left < 1) 
      return false; 
     else 
      return $key; 
    } 
1

क्यों नहीं करते हैं: :-)


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

आप बाद में कॉल पर स्कैनिंग फिर से शुरू करने के लिए अंतिम लौटाई कुंजी याद कर सकते हैं।

यदि आप चाहते हैं कि अगली कॉल समान कुंजी वापस न करें, तो आप पहले अपने कुंजी डेटाबेस को घुमा सकते हैं। इसका मतलब यह होगा कि आपको कहीं भी 456976, 1679616, 7311616, या 14776336 तत्व सरणी को पकड़ने की आवश्यकता है (इस पर निर्भर करता है कि वर्णमाला वर्ण एकल या डबल-चरण वाले वर्ण हैं, अंकों के साथ या बिना)।

0

ही अंदर एक समारोह का उपयोग करना

function test($val) { 
    /*initialize return value by using the conditions*/ 
    if($val>=5){ 
     /*do something with return statement*/ 
     return $val+10; 
    } else { 
     /*set the return default value for avoid the error throwing*/ 
     return "default value"; 
    } 
    /*return the function used for check the condition*/ 
    return test($val); 
} 

echo test(4); // output "default value"; 
echo test(6); //output 16 
संबंधित मुद्दे