Как вызвать функцию PHP из строки, хранящейся в переменной - PullRequest
262 голосов
/ 17 июня 2009

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

function foo ()
{
  //code here
}

function bar ()
{
  //code here
}

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

Любая помощь была бы великолепна.

Спасибо!

Ответы [ 15 ]

432 голосов
/ 17 июня 2009
98 голосов
/ 20 сентября 2013

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

${"variableName"} = 12;

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

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

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

17 голосов
/ 17 июня 2009

Да, это возможно:

function foo($msg) {
    echo $msg."<br />";
}
$var1 = "foo";
$var1("testing 1,2,3");

Источник: http://www.onlamp.com/pub/a/php/2001/05/17/php_foundations.html?page=2

16 голосов
/ 31 января 2013

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

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

$x = (new ReflectionFunction("foo"))->getClosure();
$x();
12 голосов
/ 30 мая 2012

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

Мой конкретный случай - реализация чьего-либо кода, связанного с цветами, и двух методов-членов lighten() и darken() из класса csscolor.php. По какой-то причине я хотел, чтобы один и тот же код мог вызывать светлее или темнее, а не выделять его с помощью логики. Это может быть результатом моего упрямства не просто использовать 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);

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

10 голосов
/ 17 июня 2009

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

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

Однако, call_user_func() - правильный путь.

6 голосов
/ 02 февраля 2014

Имена динамических функций и пространства имён

Просто чтобы добавить точку к динамическим именам функций при использовании пространств имен.

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

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);
5 голосов
/ 14 сентября 2018

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

function something() {
    echo 256;
}

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

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

$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 .

3 голосов
/ 26 ноября 2014

В дополнение к ответу @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"

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...