用字符串名调用PHP类函数

61

如何通过函数名调用一个普通的(非静态的)类函数?

下面的代码会提示一个错误,指出参数1需要一个有效的回调。我不想这个函数是静态的,我想它是一个普通的函数,但我到目前为止看到的所有示例都是静态的。

class Player
{
    public function SayHi() { print("Hi"); }
}

$player = new Player();

call_user_func($Player, 'SayHi');

请阅读他们文档中的示例4:http://php.net/manual/en/function.call-user-func.php - Matthew
我想知道它为什么没有抱怨这个问题。你声明了“player”,但是调用的是“Player”,P是大写的。 - Drazen
@drale2k:它确实在抱怨。“param 1需要是一个有效的回调函数”。 - gen_Eric
抱歉,在这个网站上只是一个拼写错误,P和p的问题。@Rocket,我明白了,但我想知道如何在php语法中修复它,就像下面的答案所提供的那样。 - user441521
1
这对我很有用,展示了几种方法,甚至建议它们之间的速度差异:https://www.designcise.com/web/tutorial/how-to-dynamically-invoke-a-class-method-in-php - Way Too Simple
6个回答

135

在PHP中,callback语法有点奇怪。你需要做的是创建一个数组,第一个元素是对象,第二个元素是方法。

call_user_func(array($player, 'SayHi'));

您也可以不使用call_user_func来实现:

$player->{'SayHi'}();
或者:
$method = 'SayHi';
$player->$method();

1
请问第三个示例有特定的名称吗? - n1nsa1d00
1
第二种方法叫什么? - Zack
3
@Zack 我知道现在可能有点晚了,但是对于将来的人们,这被称为“可变函数” [手册](https://www.php.net/manual/zh/functions.variable-functions.php),对于变量则被称为“可变变量” [手册](https://www.php.net/manual/zh/language.variables.variable.php) - rkd.me

11

你需要将对象和方法一起作为一个数组传递:

call_user_func(array($Player, 'SayHi'));

请查看回调函数,具体而言:

// Type 3: Object method call
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));

5
我在此回答一个不同的问题(PHP - Can you assign a member function to a variable?),因为一些stackoverflow激进分子将其标记为重复问题,我无法回答他的问题! Stackoverflow狂热粉丝的心态需要停止。

顺便说一下,通常这是反模式:

$a = 'Pl';
$b = 'aye';
$c = 'r';

$z = $a . $b . $c;

$myz = new $z();


$d = 'Say';
$e = 'Hi';

$x = $d.$e;
$myz->{$x}()

现在将所有变量分散到您的代码中。您已成为反基督。

为什么?因为没有人能再读懂您的代码,包括您自己。

更好的做法是在代码中实际引用函数调用。不要隐藏在某些晦涩的字符串中。而是将标准调用包装成一个函数。

尽可能保持简单。因此,更好的解决方案是:

$x = function(){
  $player = new Player();
  $player->sayHi();
};


$x();

如果您的代码中包含$myz->{$x}()这样的引用,您的IDE将会找到这些引用。但是,如果您的代码中包含$myz->x()这样的引用,您的IDE将无法找到并且您将无法很好地维护您的代码。


2

我想为那些具有参数的类函数添加答案:

class Player{
    public function Say($what){ print($what); }
}

$player = new Player();
call_user_func_array( [ $player, 'Say' ], [ 'Hi' ] );

如果您的函数“Player”有更多参数,您可以将它们放在“call_user_func_array”的第二个数组中:
class Player{
    public function Say($what,$end){ print($what.$end); }
}

$player = new Player();
call_user_func_array( [ $player, 'Say' ], [ 'Hi','gh' ] );

-1

无论如何,您都要创建一个类的对象,因此可以使用该对象调用其函数。

$player = new Player();
$player->SayHi();

或者使用回调函数

$player = new Player();
call_user_func(array($player, 'SayHi'));

2
那只是一个示例。我需要将对象及其函数作为回调函数存储起来,这些回调函数将从另一个系统触发执行,但我不想手动输入这段代码。 - user441521

-8

$player->SayHi();

我更喜欢这种形式。


5
然而,这并没有解答问题。-1 - Matt Ball
1
你是指 $player->$SayHi() 吗? - greenoldman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接