2008-09-08 36 views

उत्तर

157

मैनुअल शब्दावलियों का प्रयोग पारंपरिक रूप से "के लिए कॉलबैक" और "प्रतिदेय" दूसरे के स्थान पर, तथापि, "कॉलबैक" एक स्ट्रिंग या सरणी मान को संदर्भित करता है जो function pointer जैसा कार्य करता है, भविष्य के आमंत्रण के लिए फ़ंक्शन या क्लास विधि का संदर्भ देता है। यह PHP 4 के बाद से कार्यात्मक प्रोग्रामिंग के कुछ तत्वों को अनुमति दी गई है जायके हैं:

$cb1 = 'someGlobalFunction'; 
$cb2 = ['ClassName', 'someStaticMethod']; 
$cb3 = [$object, 'somePublicMethod']; 

// this syntax is callable since PHP 5.2.3 but a string containing it 
// cannot be called directly 
$cb2 = 'ClassName::someStaticMethod'; 
$cb2(); // fatal error 

// legacy syntax for PHP 4 
$cb3 = array(&$object, 'somePublicMethod'); 

यह एक सुरक्षित तरीका सामान्य रूप में प्रतिदेय मूल्यों का उपयोग करने के लिए है:

if (is_callable($cb2)) { 
    // Autoloading will be invoked to load the class "ClassName" if it's not 
    // yet defined, and PHP will check that the class has a method 
    // "someStaticMethod". Note that is_callable() will NOT verify that the 
    // method can safely be executed in static context. 

    $returnValue = call_user_func($cb2, $arg1, $arg2); 
} 

आधुनिक पीएचपी संस्करणों की अनुमति देने के पहले तीन प्रारूपों ऊपर $cb() के रूप में सीधे लागू किया जाना चाहिए। call_user_func और call_user_func_array उपर्युक्त सभी का समर्थन करते हैं।

देखें: http://php.net/manual/en/language.types.callable.php

नोट्स/चेतावनियां:

  1. समारोह/वर्ग namespaced है, तो स्ट्रिंग पूरी तरह से योग्य नाम होना चाहिए। जैसे ['Vendor\Package\Foo', 'method']
  2. call_user_func संदर्भ द्वारा गैर वस्तुओं गुजर का समर्थन नहीं करता है, तो आप call_user_func_array उपयोग कर सकते हैं या, बाद में पीएचपी संस्करणों में, एक वर को कॉलबैक बचाने के लिए और प्रत्यक्ष सिंटैक्स का उपयोग करें: $cb();
  3. __invoke() विधि (अज्ञात कार्यों समेत) के साथ ऑब्जेक्ट्स "कॉल करने योग्य" श्रेणी के अंतर्गत आते हैं और इसका उपयोग उसी तरह किया जा सकता है, लेकिन मैं व्यक्तिगत रूप से इन्हें विरासत "कॉलबैक" अवधि से संबद्ध नहीं करता हूं।
  4. विरासत create_function() एक वैश्विक कार्य बनाता है और इसका नाम देता है। यह eval() के लिए एक रैपर है और इसके बजाय अनाम कार्यों का उपयोग किया जाना चाहिए।
+1

बनाया है यह ओपी के स्वीकृत आत्म-उत्तर से काफी बेहतर है। – chaos

+0

दरअसल, फ़ंक्शन का उपयोग करना इसे करने का उचित तरीका है। एक चर का उपयोग करते हुए और फिर इसे कॉल करते हुए, स्वीकृत उत्तर में सुझाए गए अनुसार यह अच्छा है, यह बदसूरत है और कोड के साथ अच्छी तरह से स्केल नहीं करेगा। – icco

+3

स्वीकृत उत्तर बदल दिया। टिप्पणियों से सहमत, यह एक अच्छा जवाब है। –

26

एक कॉलबैक का क्रियान्वयन तो

// This function uses a callback function. 
function doIt($callback) 
{ 
    $data = "this is my data"; 
    $callback($data); 
} 


// This is a sample callback function for doIt(). 
function myCallback($data) 
{ 
    print 'Data is: ' . $data . "\n"; 
} 


// Call doIt() and pass our sample callback function's name. 
doIt('myCallback'); 

प्रदर्शित करता है की तरह किया जाता है: डेटा है: यह मेरा डेटा

है
+16

हे भगवान! क्या यह मानक है? वह भयानक है! –

+0

ऊपर दिखाए गए अनुसार इसे करने के कुछ अन्य तरीके हैं। मैंने वास्तव में वही सोचा। –

+0

वाह, यह पारंपरिक प्रोग्रामिंग में कुछ नए मोड़ जोड़ता है। –

9

एक गंधा चाल है कि मैं हाल ही में पाया है PHP के create_function() उपयोग करने के लिए एक गुमनाम बनाने के लिए है/लैम्ब्डा फ़ंक्शन एक-शॉट उपयोग के लिए। यह PHP कार्यों के लिए उपयोगी है जैसे array_map(), preg_replace_callback(), या usort() जो कस्टम प्रसंस्करण के लिए कॉलबैक का उपयोग करते हैं। ऐसा लगता है कि यह कवर के तहत eval() करता है, लेकिन यह अभी भी PHP का उपयोग करने के लिए एक अच्छा कार्यात्मक-शैली तरीका है।

+6

दुर्भाग्यवश, कचरा कलेक्टर इस मेमोरी के संभावित स्मृति रिसाव के उत्पादन के साथ बहुत अच्छी तरह से नहीं खेलता है। यदि आप प्रदर्शन के लिए बाहर हैं, तो create_function() से बचें। – fuxia

+1

ओच। सर उठाने के लिए धन्यवाद। – yukondude

3

मैं हर बार क्रिंग करता हूं जब मैं create_function() php में उपयोग करता हूं।

पैरामीटर एक कोमा से अलग स्ट्रिंग हैं, एक स्ट्रिंग में पूरे फ़ंक्शन बॉडी ... अरग ... मुझे लगता है कि अगर वे कोशिश करते हैं तो भी वे इसे उलझन में नहीं बना सकते थे।

दुर्भाग्यवश, नामित फ़ंक्शन बनाते समय यह एकमात्र विकल्प है जो मुसीबत के लायक नहीं है।

+0

और, ज़ाहिर है, यह रनटाइम स्ट्रिंग eval है, इसलिए यह वैध वाक्यविन्यास या संकलन समय पर किसी और चीज के लिए चेक नहीं किया जाता है। – hobbs

7

ठीक है ... 5.3 क्षितिज पर के साथ, सभी बेहतर होगा, क्योंकि 5.3 के साथ, हम बंद मिलता है और उन लोगों के साथ अनाम प्रक्रियाएं

http://wiki.php.net/rfc/closures

7

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

function doIt($callback) { 
    if(function_exists($callback)) { 
     $callback(); 
    } else { 
     // some error handling 
    } 
} 
+0

क्या होगा यदि कॉलबैक फ़ंक्शन नहीं है, लेकिन ऑब्जेक्ट और विधि रखने वाला सरणी है? –

+0

या 'is_callable ($ कॉलबैक)' –

+0

दोनों अच्छे सुझाव हैं - कॉलबैक करने के तरीके के बारे में अपने विशेष कार्यान्वयन की जांच करना आवश्यक होगा। मैं ऐसा कुछ कहने के खिलाफ चेतावनी देने की उम्मीद कर रहा था जो घातक होने के कारण अस्तित्व में नहीं था। मैंने उत्तर अधिक सामान्य – SeanDowney

4

create_function कक्षा के अंदर मेरे लिए काम नहीं किया। मुझे call_user_func का उपयोग करना पड़ा।

<?php 

class Dispatcher { 
    //Added explicit callback declaration. 
    var $callback; 

    public function Dispatcher($callback){ 
     $this->callback = $callback; 
    } 

    public function asynchronous_method(){ 
     //do asynch stuff, like fwrite...then, fire callback. 
     if (isset($this->callback)) { 
      if (function_exists($this->callback)) call_user_func($this->callback, "File done!"); 
     } 
    } 

} 

फिर, उपयोग करने के लिए:

<?php 
include_once('Dispatcher.php'); 
$d = new Dispatcher('do_callback'); 
$d->asynchronous_method(); 

function do_callback($data){ 
    print 'Data is: ' . $data . "\n"; 
} 
?> 

[संपादित करें] जोड़ा एक लापता कोष्टक। इसके अलावा, कॉलबैक घोषणा को जोड़ा गया, मैं इसे इस तरह से पसंद करता हूं।

function doIt($callback) { $callback(); } 

doIt(function() { 
    // this will be done 
}); 

अंत में एक अच्छा यह करने के लिए जिस तरह से:

+1

क्या डिस्पैचर क्लास को इस के लिए एक विशेषता की आवश्यकता नहीं है-> कॉलबैक = $ कॉलबैक काम करने के लिए? –

+0

@ जेम्स पॉल्सन: PHP एक गतिशील भाषा है, इसलिए यह काम करता है। लेकिन मैं आलसी था। मैं आमतौर पर संपत्ति घोषित करता हूं, हर किसी के जीवन को आसान बनाता है। आपके प्रश्न ने मुझे उस कोड को फिर से देखा और एक वाक्यविन्यास त्रुटि को खोजा, आप। धन्यवाद – goliatone

+0

मुझे नहीं पता था कि यह संभव था। जवाब के लिए धन्यवाद :) । –

59

पीएचपी 5.3 के साथ, अब यह कर सकते हैं। PHP के लिए एक बढ़िया जोड़ा, क्योंकि कॉलबैक भयानक हैं।

+4

सुंदर साफ, यह बहुत उपयोगी है – Ulterior

1

उन लोगों के लिए जो PHP < 5.4 के साथ संगतता को तोड़ने की परवाह नहीं करते हैं, मैं क्लीनर कार्यान्वयन करने के लिए प्रकार संकेत का उपयोग करने का सुझाव दूंगा।

function call_with_hello_and_append_world(callable $callback) 
{ 
    // No need to check $closure because of the type hint 
    return $callback("hello")."world"; 
} 

function append_space($string) 
{ 
    return $string." "; 
} 

$output1 = call_with_hello_and_append_world(function($string) { return $string." "; }); 
var_dump($output1); // string(11) "hello world" 

$output2 = call_with_hello_and_append_world("append_space"); 
var_dump($output2); // string(11) "hello world" 

$old_lambda = create_function('$string', 'return $string." ";'); 
$output3 = call_with_hello_and_append_world($old_lambda); 
var_dump($output3); // string(11) "hello world" 
संबंधित मुद्दे