Answers:
is_callable
功能。它将检查变量是否包含可以称为函数的内容(例如,函数的名称,包含对象实例和函数名称的数组或匿名函数/闭包)
call_user_func(array('ClassName', 'method'), $args)
我最喜欢的版本是内联版本:
${"variableName"} = 12;
$className->{"propertyName"};
$className->{"methodName"}();
StaticClass::${"propertyName"};
StaticClass::{"methodName"}();
您也可以将变量或表达式放在方括号内!
{"functionName"}();
不合法,将引发语法错误。
是的,有可能:
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
如前所述,有几种方法可能是最安全的方法,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);
}
如果有人因为试图将变量用于类中的方法而被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);
上面的尝试会警告该方法需要第二个参数(百分比)。
迟了几年,但这是恕我直言的最好方式:
$x = (new ReflectionFunction("foo"))->getClosure();
$x();
注意:有关摘要版本,请参见答案末尾的TL; DR。
更新:此处介绍的一种旧方法已被删除。请参阅其他答案以获取有关其他方法的解释,此处不介绍。顺便说一句,如果这个答案没有帮助您,您应该返回升级您的东西。对PHP 5.6的支持已在2019年1月结束(现在甚至不支持PHP 7.0和7.1)。有关更多信息,请参见支持的版本。
正如其他人提到的那样,在PHP5(以及类似PHP7的较新版本)中,我们可以将变量用作函数名,use 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讨论。
(expressions)->$bar()
只是为了在使用名称空间时添加有关动态函数名称的要点。
如果您使用的是名称空间,则以下内容将不起作用,除非您的函数位于全局名称空间中:
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);
如果要调用对象的方法,可以补充@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"
我在这里张贴了另一个例子
假设我有以下变量和函数:
$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";
}
调用不带参数的函数
// Calling sayHello()
call_user_func($functionName1);
你好!
用1个参数调用函数
// Calling sayHelloTo("John")
call_user_func($functionName2, $friend);
尊敬的约翰,您好!
调用带有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);
亲爱的莎拉,你好吗?
再见!
以下代码可以帮助编写PHP动态函数。现在可以通过变量“ $ current_page”动态更改函数名称。
$current_page = 'home_page';
$function = @${$current_page . '_page_versions'};
$function = function() {
echo 'current page';
};
$function();
使用存储在变量中的名称安全地调用函数的最简单方法是:
//I want to call method deploy that is stored in functionname
$functionname = 'deploy';
$retVal = {$functionname}('parameters');
我使用了如下所示的动态创建Laravel迁移表的方法,
foreach(App\Test::$columns as $name => $column){
$table->{$column[0]}($name);
}
我想到的一种非常规方法是,除非您通过某种自我编写的超级超自治AI生成整个代码,否则很有可能您要“动态”调用的功能已经在代码中定义了基础。那么,为什么不只是检查一下琴弦,然后做臭名昭著的ifelse
舞蹈来召唤……你就明白了。
例如。
if($functionName == 'foo'){
foo();
} else if($functionName == 'bar'){
bar();
}
switch-case
如果您不喜欢ifelse
梯子平淡的味道,甚至可以使用。
我了解在某些情况下“ 动态调用函数 ”是绝对必要的(就像一些修改自身的递归逻辑)。但是,大多数日常琐碎的用例都可以躲开。
它消除了应用程序的许多不确定性,同时如果字符串与任何可用函数的定义都不匹配,则使您有机会执行后备函数。恕我直言。
if (method_exists($functionName)) $functionName(); else //exception or handle