एक चर में संग्रहीत स्ट्रिंग से एक फ़ंक्शन को कैसे कॉल करें?


289

मुझे एक फ़ंक्शन कॉल करने में सक्षम होने की आवश्यकता है, लेकिन फ़ंक्शन नाम एक चर में संग्रहीत है, क्या यह संभव है? उदाहरण के लिए:

समारोह फू ()
{
  // यहाँ कोड
}

फ़ंक्शन बार ()
{
  // यहाँ कोड
}

$ फ़ंक्शन नाम = "फू";
// मुझे $ functionName क्या है के आधार पर फ़ंक्शन को कॉल करने की आवश्यकता है

जवाबों:


465

85
यदि आपको किसी ऑब्जेक्ट के फ़ंक्शन को कॉल करने की आवश्यकता है जिसका नाम एक चर में है, तो इसे कॉल करें: call_user_func (सरणी ($ obj, $ func), $ params)
BlackDivine

1
यदि आप कक्षाओं और विधियों के साथ काम कर रहे हैं, तो नीचे मेरा उत्तर भी देखें। मुझे उम्मीद नहीं थी कि मुझे क्या मिला।
क्रिस के

यदि फ़ंक्शन को परिभाषित नहीं किया गया था, तो मैं फ़ंक्शन की परिभाषा को कैसे शून्य कर सकता हूं? अगर ($ functionName) पर्याप्त है?
सईदबकर

14
@ s @мsєм: आपको is_callableफ़ंक्शन का उपयोग करना चाहिए । यह जाँच करेगा कि एक चर में कुछ ऐसा है जिसे एक फ़ंक्शन के रूप में कहा जा सकता है (जैसे कि यह एक फ़ंक्शन का नाम है, एक सरणी जिसमें ऑब्जेक्ट इंस्टेंस है और एक फ़ंक्शन नाम, या एक अनाम फ़ंक्शन / क्लोजर है)
knittl

6
@ स्पेसर: सरणी के पहले तत्व के रूप में क्लासनाम प्रदान करें:call_user_func(array('ClassName', 'method'), $args)
नाइट जूल

122

मेरा पसंदीदा संस्करण इनलाइन संस्करण है:

${"variableName"} = 12;

$className->{"propertyName"};
$className->{"methodName"}();

StaticClass::${"propertyName"};
StaticClass::{"methodName"}();

आप कोष्ठक के अंदर भी चर या भाव रख सकते हैं!


1
@marcioAlmada: इस तरीके से दूसरों के उत्तरों को संपादित करने के बजाय एक टिप्पणी पोस्ट करें; यह भ्रम जोड़ता है - यह स्पष्ट नहीं है कि किसने क्या कहा [जिज्ञासु: स्पष्टीकरण के लिए संशोधन देखें]
क्राइगर

4
ठीक है @kryger। पंक्ति 2 {"functionName"}();कानूनी नहीं है और एक सिंटैक्स त्रुटि को फेंक देगा।
marcio

4
धन्यवाद दोस्तों, उत्तर के लिए, यह वास्तव में एक त्रुटि फेंकता है, यहां तक ​​कि php 5.4 में भी, ताकि वाक्यविन्यास केवल ऑब्जेक्ट विधियों के साथ काम करे। पद का संपादन किया।
लाजोस मेस्सरोस


18

जैसा कि पहले ही उल्लेख किया गया है, इसे प्राप्त करने के कुछ तरीके हैं जो संभवतः सबसे सुरक्षित विधि है call_user_func()या यदि आपको अवश्य ही मार्ग के नीचे जाना है $function_name()। इन दोनों विधियों का उपयोग करके तर्कों को पारित करना संभव है

$function_name = 'foobar';

$function_name(arg1, arg2);

call_user_func_array($function_name, array(arg1, arg2));

यदि आप जिस फ़ंक्शन को कॉल कर रहे हैं वह किसी ऑब्जेक्ट का है तो आप अभी भी इनमें से किसी एक का उपयोग कर सकते हैं

$object->$function_name(arg1, arg2);

call_user_func_array(array($object, $function_name), array(arg1, arg2));

हालाँकि, यदि आप $function_name()विधि का उपयोग करने जा रहे हैं तो फ़ंक्शन के अस्तित्व के लिए परीक्षण करना एक अच्छा विचार हो सकता है यदि नाम किसी भी तरह से गतिशील है

if(method_exists($object, $function_name))
{
    $object->$function_name(arg1, arg2);
}

13

यदि कोई व्यक्ति Google द्वारा यहां लाया जाता है, क्योंकि वे एक वर्ग के भीतर एक विधि के लिए एक चर का उपयोग करने की कोशिश कर रहे थे, तो नीचे एक कोड नमूना है जो वास्तव में काम करेगा। उपरोक्त में से किसी ने भी मेरी स्थिति के लिए काम नहीं किया। &घोषित करने $c = & new...और &$cपारित होने में महत्वपूर्ण अंतर है call_user_func

मेरा विशिष्ट मामला है जब किसी के कोड को रंगों और दो सदस्य विधियों lighten()और darken()csscolor.php वर्ग से लागू करना है। जो भी कारण के लिए, मैं चाहता था कि एक ही कोड तर्क के साथ इसे चुनने के बजाय हल्का या गहरा करने में सक्षम हो। यह मेरी जिद का नतीजा हो सकता है कि अगर इस पद्धति का उपयोग न किया जाए या कोड को बदल दिया जाए।

$lightdark="lighten"; // or optionally can be darken
$color="fcc";   // a hex color
$percent=0.15;  
include_once("csscolor.php");
$c = & new CSS_Color($color);
$rtn=call_user_func( array(&$c,$lightdark),$color,$percent);

ध्यान दें कि कुछ भी $c->{...}काम नहीं कर रहा था। Php.net के पेज पर नीचे की ओर पाठक द्वारा योगदान की गई सामग्री के लिए मना call_user_funcकरने पर , मैं ऊपर एक साथ टुकड़ा करने में सक्षम था। यह भी ध्यान दें कि $paramsएक सरणी के रूप में मेरे लिए काम नहीं किया :

// This doesn't work:
$params=Array($color,$percent);
$rtn=call_user_func( array(&$c,$lightdark),$params);

ऊपर दिए गए इस प्रयास से दूसरे तर्क (प्रतिशत) की अपेक्षा की गई विधि के बारे में एक चेतावनी मिलेगी।


"$ c = & new CSS_Color" क्या करता है? मैं amp (और) के बारे में बात कर रहा हूं। यह क्या बदलता है?
दानोन

@danon & "का पता" या "संदर्भ" ऑपरेटर है। मैं वर्ग CSS_Color की एक नई वस्तु को स्थापित कर रहा हूं और फिर $ c को इसके संदर्भ (उर्फ पता) सौंप रहा हूं। मुझे दोहराए जाने वाले कोड से नफरत है, इसलिए मैं अक्सर चर चर नामों का उपयोग करता हूं।
क्रिस के

1
मुझे समझ नहीं आ रहा है। कहीं भी सभी वस्तुओं को संदर्भ से पारित नहीं किया जाता है? मेरा मतलब है, यदि आप एक समारोह में $ c को पास करते हैं और इसे बदलते हैं, तो मूल वस्तु भी प्रभावित होगी, है ना? कोई फर्क नहीं पड़ता कि आपने यह प्रयोग किया है या नहीं, क्या मैं सही हूं?
दानोन

मैंने प्रतीकों के विभिन्न संयोजनों की कोशिश की और केवल php.org पर उपयोगकर्ता टिप्पणियों को पढ़ते समय मैं काम कर पाने में सक्षम था। आपको php के व्यवहार के लिए जिम्मेदार लोगों के साथ उस चर्चा को शुरू करना होगा।
क्रिस के

दूसरे उदाहरण के लिए आप गलत थे, आप
call_user_func_array

13

कुछ साल देर से, लेकिन यह अब तक का सबसे अच्छा तरीका है:

$x = (new ReflectionFunction("foo"))->getClosure();
$x();

3
मेरे लिए OOP का रास्ता है, लेकिन मैंने इसे +1 दिया, क्योंकि किसी ने अभी तक रिफ्लेक्शन क्लास का उल्लेख नहीं किया है।
लाजोस मेसाज़्रोस

इस उत्तर को न समझें। क्या समस्या हल हो रही है, बिल्कुल?
डेविड स्पेक्टर

10

पूर्णता के लिए, आप eval () का भी उपयोग कर सकते हैं :

$functionName = "foo()";
eval($functionName);

हालाँकि, call_user_func()उचित तरीका है।


8
यह ध्यान दिया जाना चाहिए कि eval () समान व्यवहार की अनुमति देगा लेकिन यह किसी भी PHP कोड को निष्पादित करने की अनुमति देगा। इसलिए सिस्टम को हाईजैक करने के लिए वैरिएबल का इस्तेमाल किया जा सकता है। Call_user_func () ऐसे सुरक्षा मुद्दों को नहीं लाता है।
जॉन

4
evalइस सवाल का हल नहीं है।
एकर

1
कृपया ऐसा न करें क्योंकि एक हमलावर आपके सर्वर को पूरी तरह से मिटा सकता है।
andreszs

10

समाधान: PHP7 का उपयोग करें

नोट: संक्षेप संस्करण के लिए, उत्तर के अंत में TL; DR देखें।

पुराने तरीके

अपडेट : यहां बताए गए पुराने तरीकों में से एक को हटा दिया गया है। अन्य तरीकों पर स्पष्टीकरण के लिए अन्य उत्तरों का संदर्भ लें, यह यहां कवर नहीं किया गया है। वैसे, यदि यह उत्तर आपकी मदद नहीं करता है, तो आपको अपना सामान अपग्रेड करना चाहिए। PHP 5.6 समर्थन जनवरी 2019 में समाप्त हो गया है (अब भी PHP 7.0 और 7.1 समर्थित नहीं हैं)। अधिक जानकारी के लिए समर्थित संस्करण देखें ।

जैसा कि दूसरों ने उल्लेख किया है, PHP5 में (और PHP7 जैसे नए संस्करणों में भी) हम फ़ंक्शन नाम, उपयोग call_user_func()और call_user_func_array()(जो, व्यक्तिगत रूप से, मैं उन कार्यों से नफरत करता हूं), आदि के रूप में चर का उपयोग कर सकता हूं।

नए तरीके

PHP7 के रूप में, नए तरीके पेश किए गए हैं:

नोट:<something> कोष्ठक के अंदर सब कुछ एक या अधिक अभिव्यक्तियों का <function_name>अर्थ है कुछ बनाने के लिए, जैसे कि फ़ंक्शन नाम बनाने वाले भाव।

डायनामिक फंक्शन कॉल: फंक्शन नाम ऑन-द-फ्लाई

हम कोष्ठक के अंदर एक या एक से अधिक अभिव्यक्तियों का उपयोग केवल एक बार में फ़ंक्शन नाम के रूप में कर सकते हैं:

(<function_name>)(arguments);

उदाहरण के लिए:

function something(): string
{
    return "something";
}

$bar = "some_thing";

(str_replace("_", "", $bar))(); // something

// Possible, too; but generally, not recommended, because makes your code more complicated
(str_replace("_", "", $bar))()(); 

नोट: हालाँकि, चारों ओर कोष्ठक हटाना str_replace()कोई त्रुटि नहीं है, कोष्ठक डालने से कोड अधिक पठनीय हो जाता है। हालाँकि, आप कभी-कभी ऐसा नहीं कर सकते, जैसे कि .ऑपरेटर का उपयोग करते समय । सुसंगत होने के लिए, मैं आपको कोष्ठकों को हमेशा लगाने की सलाह देता हूं।

डायनेमिक मेथड कॉल: मेथड नेम-ऑन-द-फ्लाई

गतिशील फ़ंक्शन कॉल की तरह, हम उसी तरह से कर सकते हैं जैसे विधि कॉल, कोष्ठक के बजाय घुंघराले ब्रेसिज़ से घिरा हुआ (अतिरिक्त रूपों के लिए, TL पर जाएं; DR अनुभाग);

$object->{<method_name>}(arguments);
$object::{<method_name>}(arguments);

इसे एक उदाहरण में देखें:

class Foo
{
    public function another(): string
    {
        return "something";
    }
}

$bar = "another thing";

(new Something())->{explode(" ", $bar)[0]}(); // something

डायनेमिक विधि कॉल: ऐरे सिंटैक्स

PHP7 में जोड़ा गया अधिक सुंदर तरीका निम्नलिखित है:

[<object>, <method_name>](arguments);
[<class_name>, <method_name>](arguments); // Static calls only

उदहारण के लिए:

class Foo
{
    public function nonStaticCall()
    {
        echo "Non-static call";
    }
    public static function staticCall()
    {
        echo "Static call";
    }
}

$x = new X();

[$x, "non" . "StaticCall"](); // Non-static call
[$x, "static" . "Call"](); // Static call

नोट: पिछले एक से अधिक इस पद्धति का उपयोग करने का लाभ यह है कि, आपको कॉल प्रकार (यानी यह स्थिर है या नहीं) के बारे में परवाह नहीं है।

अतिरिक्त उदाहरण: बेनामी वर्गों का उपयोग करना

चीजों को थोड़ा जटिल बनाते हुए, आप अनाम कक्षाओं और उपरोक्त सुविधाओं के संयोजन का उपयोग कर सकते हैं :

$bar = "SomeThing";

echo (new class {
    public function something()
    {
        return 512;
    }
})->{strtolower($bar)}(); // 512

टीएल; डीआर (निष्कर्ष)

आमतौर पर, PHP7 में, निम्नलिखित रूपों का उपयोग करना संभव है:

// Everything inside `<something>` brackets means one or more expressions
// to form something

// Dynamic function call
(<function_name>)(arguments)

// Dynamic method call on an object
$object->{<method_name>}(arguments)
$object::{<method_name>}(arguments)

// Dynamic method call on a dynamically-generated object
(<object>)->{<method_name>}(arguments)
(<object>)::{<method_name>}(arguments)

// Dynamic method call, statically
ClassName::{<method_name>}(arguments)
(<class_name>)::{<method_name>}(arguments)

// Dynamic method call, array-like (no different between static and non-static calls
[<object>, <method_name>](arguments)

// Dynamic method call, array-like, statically
[<class_name>, <method_name>](arguments)

ज्यादातर इस PHP पर आधारित बात करते हैं


1
भावों की अच्छी सूची, इसमें ये भी शामिल हैं:(expressions)->$bar()
नेक्रो

1
@ नेक्रो थैंक्स, मैंने इसे जोड़ा!
मचिट्ठार्ग

8

डायनामिक फ़ंक्शन नाम और नामस्थान

बस नाम स्थान का उपयोग करते समय गतिशील फ़ंक्शन नामों के बारे में एक बिंदु जोड़ने के लिए।

यदि आप नामस्थान का उपयोग कर रहे हैं, तो निम्न कार्य नहीं करेगा सिवाय यदि आपका फ़ंक्शन वैश्विक नामस्थान में है:

namespace greetings;

function hello()
{
    // do something
}

$myvar = "hello";
$myvar(); // interpreted as "\hello();"

क्या करें?

आपको call_user_func()इसके बजाय उपयोग करना होगा:

// if hello() is in the current namespace
call_user_func(__NAMESPACE__.'\\'.$myvar);

// if hello() is in another namespace
call_user_func('mynamespace\\'.$myvar);

4

यदि आप किसी ऑब्जेक्ट की विधि को कॉल करना चाहते हैं, तो @Chris K के उत्तर को लागू करते हुए, आप इसे एक बंद की मदद से एकल चर का उपयोग करके कॉल कर सकते हैं:

function get_method($object, $method){
    return function() use($object, $method){
        $args = func_get_args();
        return call_user_func_array(array($object, $method), $args);           
    };
}

class test{        

    function echo_this($text){
        echo $text;
    }
}

$test = new test();
$echo = get_method($test, 'echo_this');
$echo('Hello');  //Output is "Hello"

मैंने यहां एक और उदाहरण पोस्ट किया


4

मैंने इस प्रश्न और उत्तरों से क्या सीखा। सबको शुक्रीया!

मान लीजिए कि मेरे पास ये चर और कार्य हैं:

$functionName1 = "sayHello";
$functionName2 = "sayHelloTo";
$functionName3 = "saySomethingTo";

$friend = "John";
$datas = array(
    "something"=>"how are you?",
    "to"=>"Sarah"
);

function sayHello()
{
echo "Hello!";
}

function sayHelloTo($to)
{
echo "Dear $to, hello!";
}

function saySomethingTo($something, $to)
{
echo "Dear $to, $something";
}
  1. तर्कों के बिना फ़ंक्शन को कॉल करने के लिए

    // Calling sayHello()
    call_user_func($functionName1); 

    हैलो!

  2. 1 तर्क के साथ फ़ंक्शन को कॉल करने के लिए

    // Calling sayHelloTo("John")
    call_user_func($functionName2, $friend);

    प्रिय जॉन, नमस्ते!

  3. 1 या अधिक तर्कों के साथ फ़ंक्शन को कॉल करने के लिए यह उपयोगी होगा यदि आप गतिशील रूप से अपने कार्यों को कॉल कर रहे हैं और प्रत्येक फ़ंक्शन में विभिन्न तर्क हैं। यह मेरा मामला है जिसे मैं (और हल) ढूंढ रहा हूं। call_user_func_arrayक्या चाबी है

    // You can add your arguments
    // 1. statically by hard-code, 
    $arguments[0] = "how are you?"; // my $something
    $arguments[1] = "Sarah"; // my $to
    
    // 2. OR dynamically using foreach
    $arguments = NULL;
    foreach($datas as $data) 
    {
        $arguments[] = $data;
    }
    
    // Calling saySomethingTo("how are you?", "Sarah")
    call_user_func_array($functionName3, $arguments);

    प्रिय सारा, आप कैसे हैं?

याय बाय!



2

निम्नलिखित कोड PHP में गतिशील फ़ंक्शन लिखने में मदद कर सकता है। अब फ़ंक्शन का नाम डायनामिक रूप से परिवर्तनशील '$ current_page' द्वारा किया जा सकता है।

$current_page = 'home_page';
$function = @${$current_page . '_page_versions'};
$function = function() {
    echo 'current page';
};
$function();

अनाम फ़ंक्शंस (यानी डायनेमिक फ़ंक्शंस) वैरिएबल फ़ंक्शंस (यानी गतिशील रूप से कॉलिंग फ़ंक्शंस ) से भिन्न होते हैं । इसके अलावा, आप $functionबिना किसी कारण के चर की जगह ले रहे हैं ।
मचिट्ठार्ग

1

एक चर में संग्रहीत नाम का उपयोग करके किसी फ़ंक्शन को कॉल करने का सबसे आसान तरीका है,

//I want to call method deploy that is stored in functionname 
$functionname = 'deploy';

$retVal = {$functionname}('parameters');

मैंने नीचे की तरह का उपयोग किया है गतिशील रूप से लारवेल में माइग्रेशन टेबल बनाने के लिए,

foreach(App\Test::$columns as $name => $column){
        $table->{$column[0]}($name);
}

-4

एक अपरंपरागत दृष्टिकोण, जो मेरे दिमाग में आया है, जब तक कि आप कुछ सुपर अल्ट्रा स्वायत्त एआई के माध्यम से पूरे कोड को उत्पन्न नहीं कर रहे हैं , जो खुद लिखता है , ऐसे उच्च संभावनाएं हैं कि जिन कार्यों को आप "गतिशील रूप से" कॉल करना चाहते हैं, वे पहले से ही आपके कोड में परिभाषित हैं। आधार। तो क्यों न केवल स्ट्रिंग की जांच करें और कुख्यात ifelseनृत्य को बुलाने के लिए ... आप मेरी बात समझें।

जैसे।

if($functionName == 'foo'){
  foo();
} else if($functionName == 'bar'){
  bar();
}

यहां तक ​​कि switch-caseइस्तेमाल किया जा सकता है अगर आपको ifelseसीढ़ी के नरम स्वाद पसंद नहीं है ।

मैं समझता हूं कि ऐसे मामले हैं जहां " फ़ंक्शन को गतिशील रूप से कॉल करना" एक पूर्ण आवश्यकता होगी ( जैसे कुछ पुनरावर्ती तर्क जो संशोधित करता है )। लेकिन हर रोज होने वाले ज्यादातर तुच्छ उपयोग-मामले सिर्फ चकमा दे सकते हैं।

यह आपके एप्लिकेशन से बहुत अधिक अनिश्चितता का मातम करता है, जबकि अगर आपको उपलब्ध फंक्शन की परिभाषा से कोई मेल नहीं खाता है, तो आपको एक फॉलबैक फ़ंक्शन को निष्पादित करने का मौका देता है। IMHO।


यदि चर का मान पहले से ही फ़ंक्शन का नाम है तो अतिरिक्त काम क्यों करें? यह देखने के लिए कि आपके द्वारा चलाने से पहले फ़ंक्शन php द्वारा मौजूद है या नहीं, यह देखने के लिए ठोस प्रतिक्रिया प्राप्त करना अच्छा होगा: if (method_exists($functionName)) $functionName(); else //exception or handle
Necro

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

-10

मुझे नहीं पता कि आपको यू का उपयोग क्यों करना है, यह मेरे लिए बिल्कुल अच्छा नहीं है, लेकिन यदि केवल थोड़ी मात्रा में फ़ंक्शन हैं, तो आप एक / ifif निर्माण का उपयोग कर सकते हैं। मैं नहीं जानता कि क्या एक सीधा समाधान संभव है।

$ फू = "बार" जैसा कुछ; $ परीक्षण = "फू"; इको $ $ टेस्ट;

बार लौट जाना चाहिए, आप चारों ओर की कोशिश कर सकते हैं लेकिन मुझे नहीं लगता कि यह कार्यों के लिए काम करेगा

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