Как вызвать функцию из строки, хранящейся в переменной?

Мне нужно иметь возможность вызывать функцию, но имя функции хранится в переменной, это возможно? например:

function foo ()
{
  //code here
}

function bar ()
{
  //code here
}

$functionName = "foo";
// i need to call the function based on what is $functionName

Ответ 2

Моя любимая версия - встроенная версия:

${"variableName"} = 12;

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

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

Вы можете поместить переменные или выражения в скобки тоже!

Ответ 4

Как уже упоминалось, есть несколько способов достичь этого, возможно, самым безопасным способом является 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);
}

Ответ 5

В случае, если кто-то еще привезет сюда google, потому что они пытались использовать переменную для метода внутри класса, ниже приведен пример кода, который будет работать. Ничто из этого не помогло мне. Ключевым отличием является & в объявлении $c = & new... и &$c, передаваемом в call_user_func.

Моим конкретным случаем является реализация кода пользователя, связанного с цветами и двумя методами-членами lighten() и darken() из класса csscolor.php. По какой-то причине я хотел, чтобы один и тот же код мог вызвать lighten или darken, а не выбирать его с логикой. Это может быть результатом моего упрямства не просто использовать if-else, либо изменить код, вызывающий этот метод.

$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);

Эта вышеприведенная попытка даст предупреждение о методе, ожидающем второй аргумент (в процентах).

Ответ 6

Несколько лет спустя, но это лучший способ теперь imho:

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

Ответ 7

Для полноты вы также можете использовать eval():

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

Однако call_user_func() является правильным способом.

Ответ 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);

Ответ 9

Есть несколько потрясающих возможностей с PHP7. Первоначально, как уже упоминалось, в PHP5 (и даже старше PHP5) мы могли бы сделать:

function something() {
    echo 256;
}

$foo = "something";
$foo(); // 256

Это хорошо, но в PHP7 это стало лучше. Мы можем совершать произвольные операции над (a) строками в круглых скобках и использовать их как имя функции всего за один раз (рассмотрим, что мы объявили функцию something()):

$bar = "some_thing";

// We use in this form: (expressions)(arguments);
(str_replace("_", "", $bar))(); // 256

Кроме того, вы можете использовать следующую форму:

(expressions)['bar']
(expressions)->bar
(expressions)->bar()
(expressions)->$bar()
(expressions)::$bar
(expressions)::bar()
(expressions)()

Например, вы можете использовать комбинацию анонимных классов и вышеприведенную функцию:

echo (new class {
    public $something = 512;
})->something; // 512

Кроме того, вы можете вызвать метод в экземпляре класса в виде:

[objectInstance, methodName]();

В качестве примера мы могли бы сделать:

class X {
    public function object_call() {
        echo "Object Call";
    }
    public static function static_call() {
        echo "Static Call";
    }
}

[new X(), "object_call"](); // Object Call
[new X(), "static_call"](); // Static Call

Взято из этого разговора PHP.

Ответ 10

Дополняя ответ @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"

Я разместил еще один пример здесь

Ответ 11

Используйте функцию call_user_func.

Ответ 12

Что я узнал из этого вопроса и ответов. Спасибо всем!

Допустим, у меня есть эти переменные и функции:

$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); 
    

    Hello!

  2. Для вызова функции с 1 аргументом

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

    Dear John, hello!

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

    Dear Sarah, how are you?

Yay пока!

Ответ 13

Следующий код может помочь написать динамическую функцию в PHP. теперь имя функции может динамически меняться переменной '$ current_page'.

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

Ответ 14

Один необычный подход, который пришел мне на ум, заключается в том, что, если вы не генерируете весь код через супер сверхавтономный ИИ, который сам пишет, есть большие шансы, что функции, которые вы хотите "динамически" вызвать, уже определены в вашем коде база. Так почему бы не просто проверить строку и сделать позорный ifelse танец, чтобы вызвать... вы получите мою точку зрения.

например.

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

Даже switch-case можно использовать, если вам не нравится мягкий вкус лестницы ifelse.

Я понимаю, что бывают случаи, когда "динамическое вызов функции" будет абсолютной необходимостью (как и какая-то рекурсивная логика, которая модифицирует себя). Но большинство повседневных тривиальных случаев использования можно просто уклониться.

Это избавляет от неопределенности от вашего приложения, давая вам возможность выполнить функцию возврата, если строка не соответствует определению определения доступных функций. ПО МОЕМУ МНЕНИЮ.

Ответ 15

Я не знаю, почему у вас это использовать, не так хорошо звучит для меня вообще, но если есть только небольшое количество функций, вы можете использовать конструкцию if/elseif. Я не знаю, возможно ли прямое решение.

что-то вроде $ foo = "bar"; $ test = "foo"; echo $$ test;

должен возвращать бар, вы можете попробовать, но я не думаю, что это будет работать для функций