मैं PHP में कॉलबैक कैसे लागू करूं?


181

PHP में कॉलबैक कैसे लिखे जाते हैं?


1
गोना ने एक और प्रश्न को इस लिंक से जोड़ा , क्योंकि मैं एक कॉल को बंद करने की कोशिश कर रहा था।
अकुंरी

जवाबों:


173

मैनुअल "कॉलबैक" और "कॉल करने योग्य" शब्दों का परस्पर उपयोग करता है, हालांकि, "कॉलबैक" पारंपरिक रूप से एक स्ट्रिंग या सरणी मान को संदर्भित करता है जो भविष्य के आह्वान के लिए एक फ़ंक्शन या वर्ग विधि का संदर्भ देते हुए फ़ंक्शन पॉइंटर की तरह काम करता है । यह 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);
}

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

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

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

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

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

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

यह पायथन प्रोग्रामिंग से आने वाले पाठकों के लिए उत्तर में इंगित करने के लिए उपयोगी होगा कि 'someGlobalFunction'वास्तव में एक परिभाषित फ़ंक्शन है।
टीएमओटीटीएम

1
PHP 5.3 के रूप में, क्लोजर हैं, बार्ट वैन ह्युकेलोम का उत्तर देखें । यह सब विरासत की गड़बड़ी की तुलना में बहुत सरल और "मानक" है।
वास्तव में 15

हां, मैं अपने उत्तर में अनाम कार्यों का उल्लेख करता हूं, लेकिन ओपी ने "कॉलबैक" (2008 में) के लिए कहा और ये पुराने शैली के कॉलबैक अभी भी बहुत सारे हैं PHP कोडबेस के उपयोग में।
स्टीव क्ले

74

PHP 5.3 के साथ, अब आप ऐसा कर सकते हैं:

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

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

अंत में यह करने के लिए एक अच्छा तरीका है। PHP के लिए एक बढ़िया अतिरिक्त, क्योंकि कॉलबैक बहुत बढ़िया हैं।


1
यह शीर्ष उत्तर होने की आवश्यकता है।
ग्रोवर।

30

एक कॉलबैक का कार्यान्वयन इस तरह किया जाता है

// 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');

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


21
हे भगवान। क्या वह मानक है? वह भयानक है!
Nick Retallack

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

3
@ रिकॉल, मैं नहीं देखता कि इसके बारे में इतना भयानक क्या है। मैं जिन भाषाओं के बारे में जानता हूं, जैसे कि जावास्क्रिप्ट और सी #, वे सभी इस तरह के पैटर्न में अपने कॉलबैक फ़ंक्शन की संरचना कर सकते हैं। JavaScirpt और C # से आते हुए, मैं वास्तव में call_user_func () का उपयोग नहीं कर रहा हूँ। यह मुझे ऐसा महसूस कराता है कि मुझे अपने आप को दूसरे तरीके के बजाय PHP के अनुकूल बनाना है।
एंटोनी

4
@Antony मैं इस तथ्य पर आपत्ति जता रहा था कि तार इस भाषा में फ़ंक्शन संकेत हैं। मैंने उस टिप्पणी को तीन साल पहले पोस्ट किया था, इसलिए मैं अब तक इसका उपयोग कर रहा हूं, लेकिन मुझे लगता है कि PHP एकमात्र ऐसी भाषा है जिसे मैं जानता हूं (शेल स्क्रिप्टिंग के अलावा) जहां यह मामला है।
निक रिटालैक

1
@Antony मैं उसी सिंटैक्स का उपयोग करना पसंद करता हूं जिसका उपयोग मैं जावास्क्रिप्ट में करता हूं। इसलिए मुझे यह भी समझ में नहीं आता है कि call_user_func()जब लोग एक वाक्यविन्यास का उपयोग करना चाहते हैं जो उन्हें गतिशील रूप से कॉल फ़ंक्शन करने और कॉलबैक करने में सक्षम बनाता है। मैं आपसे सहमत हुँ!
बोटनवूवर

9

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


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

1
आउच। सर उठाने के लिए धन्यवाद।
युकुन्दुड़ी

क्या आप PHP 7.4 संस्करण (एरो फ़ंक्शंस) के साथ उत्तर को अपडेट करने और पदावनत के बारे में चेतावनी जोड़ने का मन करेंगे create_function()?
14

7

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

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


7

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

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

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

3
या यों कहेंis_callable( $callback )
राको सी। बुल्जन

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

5

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";
}
?>

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


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

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

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

यह डिस्पैचर ऑब्जेक्ट बनाने से पहले और async विधि को कॉल करने से पहले do_callback फ़ंक्शन को घोषित करना सुरक्षित नहीं होगा?
बेदखली e

3

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

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

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


1
और, निश्चित रूप से, यह रनटाइम स्ट्रिंग इवेल है, इसलिए इसे संकलन समय पर मान्य सिंटैक्स या किसी अन्य चीज़ के लिए चेक नहीं किया जाता है।
हॉब्स

यह उत्तर पिछले 2 वर्षों से पुराना है। create_function()अब वंचित है और इसका उपयोग नहीं किया जाना चाहिए।
धर्म

2

जो लोग 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"

चेतावनी create_function() को PHP 7.2.0 के रूप में परिभाषित किया गया है। इस समारोह पर भरोसा करना बहुत हतोत्साहित करता है।
धर्मन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.