如何从存储在Variable中的字符串调用PHP函数

Liz*_*ard 271 php dynamic-function

我需要能够调用一个函数,但函数名存储在一个变量中,这可能吗?例如:

function foo ()
{
  //code here
}

function bar ()
{
  //code here
}

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

任何帮助都会很棒.

谢谢!

kni*_*ttl 444

$functionName() 要么 call_user_func($functionName)

  • 如果需要调用一个对象的函数,其名称在变量中,请执行以下操作:call_user_func(array($ obj,$ func),$ params) (80认同)
  • @sємsєм:你应该使用[`is_callable`](http://php.net/is_callable)函数.它将检查变量是否包含可以作为函数调用的内容(无论是函数名称,包含对象实例和函数名称的数组,还是匿名函数/闭包) (14认同)
  • @Pacerier:提供classname作为数组的第一个元素:`call_user_func(array('ClassName','method'),$ args)` (6认同)

Laj*_*ros 108

我最喜欢的版本是内联版本:

${"variableName"} = 12;

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

StaticClass::${"propertyName"};
StaticClass::{"methodName"}();
Run Code Online (Sandbox Code Playgroud)

您也可以在括号内放置变量或表达式!

  • 好的@kryger.第2行`{"functionName"}();`不合法,会引发语法错误. (4认同)
  • 谢谢大家,对于回复,它确实会抛出一个错误,即使在php 5.4中,所以语法只适用于对象方法.编辑了这篇文章. (4认同)

Sev*_*Sev 17

对的,这是可能的:

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

资料来源:http://www.onlamp.com/pub/a/php/2001/05/17/php_foundations.html?page = 2


oll*_*inn 17

正如已经提到的,有几种方法可以实现这一点,可能是最安全的方法,call_user_func()或者如果你必须你也可以沿着这条路走下去$function_name().可以使用这两种方法传递参数

$function_name = 'foobar';

$function_name(arg1, arg2);

call_user_func_array($function_name, array(arg1, arg2));
Run Code Online (Sandbox Code Playgroud)

如果您调用的函数属于某个对象,您仍然可以使用其中任何一个

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

call_user_func_array(array($object, $function_name), array(arg1, arg2));
Run Code Online (Sandbox Code Playgroud)

但是,如果您要使用该$function_name()方法,如果名称以任何方式动态,则测试函数是否存在可能是个好主意

if(method_exists($object, $function_name))
{
    $object->$function_name(arg1, arg2);
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*s K 12

如果其他人被谷歌带到这里是因为他们试图将变量用于类中的方法,下面是一个实际可行的代码示例.以上都不适用于我的情况.关键的区别在于&声明$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);
Run Code Online (Sandbox Code Playgroud)

请注意,尝试任何$c->{...}不起作用.在浏览了php.net页面底部的读者提供的内容后call_user_func,我能够拼凑出上述内容.另请注意,$params由于数组对我不起作用:

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

上面的尝试会给出关于期望第二个参数(百分比)的方法的警告.


Int*_*ror 12

几年后,但这是现在最好的方式:

$x = (new ReflectionFunction("foo"))->getClosure();
$x();
Run Code Online (Sandbox Code Playgroud)

  • 我的OOP方式,但我给它+1,因为没有人提到反射类. (3认同)
  • 不明白这个答案。它到底解决了什么问题? (2认同)

kar*_*m79 10

为了完整起见,您还可以使用eval():

$functionName = "foo()";
eval($functionName);
Run Code Online (Sandbox Code Playgroud)

但是,这call_user_func()是正确的方法.

  • 应该注意的是,eval()将允许相同的行为,但它也允许执行任何PHP代码.因此该变量可用于劫持系统.call_user_func()不会带来此类安全问题. (7认同)
  • `eval`不是这个问题的解决方案. (4认同)
  • 请不要这样做,因为攻击者可能会彻底摧毁您的服务器。 (2认同)

Jiv*_*van 7

动态函数名称和名称空间

只是在使用命名空间时添加关于动态函数名称的观点.

如果您正在使用名称空间,除非您的函数位于全局名称空间中,否则以下内容将不起作用:

namespace greetings;

function hello()
{
    // do something
}

$myvar = "hello";
$myvar(); // interpreted as "\hello();"
Run Code Online (Sandbox Code Playgroud)

该怎么办?

你必须使用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);
Run Code Online (Sandbox Code Playgroud)


MAC*_*rha 6

从PHP7开始,存在一些很棒的可能性。最初,如其他人所述,在PHP5(甚至比PHP5还要老)中,我们可以做:

function something() {
    echo 256;
}

$foo = "something";
$foo(); // 256
Run Code Online (Sandbox Code Playgroud)

这很好,但是在PHP7中变得更好。我们可以对括号中的一个或多个字符串进行任意操作,然后只需一遍就可以将其用作函数名(考虑到我们已经声明了something()函数):

$bar = "some_thing";

// We use in this form: (expressions)(arguments);
(str_replace("_", "", $bar))(); // 256
Run Code Online (Sandbox Code Playgroud)

此外,您可以使用以下所有形式:

(expressions)['bar']
(expressions)->bar
(expressions)->bar()
(expressions)->$bar()
(expressions)::$bar
(expressions)::bar()
(expressions)()
Run Code Online (Sandbox Code Playgroud)

例如,您可以结合使用匿名类和上述功能:

echo (new class {
    public $something = 512;
})->something; // 512
Run Code Online (Sandbox Code Playgroud)

另外,您可以以下形式调用类实例上的方法:

[objectInstance, methodName]();
Run Code Online (Sandbox Code Playgroud)

例如,我们可以这样做:

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
Run Code Online (Sandbox Code Playgroud)

摘自此PHP演讲


Dav*_*vid 5

如果你想调用一个对象的方法,补充@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"
Run Code Online (Sandbox Code Playgroud)

我在这里发布了另一个例子