PHP中的动态类方法调用

111
有没有一种方法可以在PHP中动态调用同一个类中的方法?我不确定语法是否正确,但我想做类似于这样的事情:
$this->{$methodName}($arg1, $arg2, $arg3);

这是原始问题吗?我正在寻找动态调用方法的方法,然后我发现了这个问题。这是andy.gurin提供的相同语法,我没有看到显示问题更新的链接。无论如何...感谢提问和贡献者们 :-) - Luc M
5
@Luc - 这是最初的问题。事实证明,当我提问时我的语法是正确的,但我的代码还有其他错误,所以它没有起作用。 - VirtuosiMedia
相关,可能是重复问题(不确定哪一个更适合作为目标...)https://dev59.com/IV4b5IYBdhLWcg3wlSdq - TylerH
8个回答

208

有不止一种方法来做到这点:

$this->{$methodName}($arg1, $arg2, $arg3);
$this->$methodName($arg1, $arg2, $arg3);
call_user_func_array(array($this, $methodName), array($arg1, $arg2, $arg3));

你甚至可以使用反射API http://php.net/manual/en/class.reflection.php


我猜可能是语法没错,所以我的代码还有其他问题,因为它的功能不太正确。嗯... - VirtuosiMedia
1
对于那些使用对象并在PHPUnit中进行测试的人来说,一个疲惫的建议是:call_user_func_array 是你需要的。 - OK sure
你,我的朋友,真是救了我一天!我一直在调用 call_user_func_array($this->$name, ...),不知道为什么它不起作用! - Pubudu Dodangoda
谢谢,这对我有用。 $this->$methodName($arg1, $arg2, $arg3); - Javed Iqbal

15

您可以在PHP中使用重载:重载

class Test {

    private $name;

    public function __call($name, $arguments) {
        echo 'Method Name:' . $name . ' Arguments:' . implode(',', $arguments);
        //do a get
        if (preg_match('/^get_(.+)/', $name, $matches)) {
            $var_name = $matches[1];
            return $this->$var_name ? $this->$var_name : $arguments[0];
        }
        //do a set
        if (preg_match('/^set_(.+)/', $name, $matches)) {
            $var_name = $matches[1];
            $this->$var_name = $arguments[0];
        }
    }
}

$obj = new Test();
$obj->set_name('Any String'); //Echo:Method Name: set_name Arguments:Any String
echo $obj->get_name();//Echo:Method Name: get_name Arguments:
                      //return: Any String

13

只需省略大括号:

$this->$methodName($arg1, $arg2, $arg3);

4

您还可以使用call_user_func()call_user_func_array()


4
如果您在PHP中使用类,则我建议使用PHP5中的重载__call函数。您可以在此处找到参考资料here
基本上,__call为动态函数提供了__set和__get在OO PHP5中为变量提供的功能。

2
您可以使用闭包将一个方法存储在单个变量中:
class test{        

    function echo_this($text){
        echo $text;
    }

    function get_method($method){
        $object = $this;
        return function() use($object, $method){
            $args = func_get_args();
            return call_user_func_array(array($object, $method), $args);           
        };
    }
}

$test = new test();
$echo = $test->get_method('echo_this');
$echo('Hello');  //Output is "Hello"

编辑:我已经编辑了代码,现在它与PHP 5.3兼容。另一个示例在这里


2

就我的情况而言。

$response = $client->{$this->requestFunc}($this->requestMsg);

使用PHP SOAP。

2
我不确定,但要注意安全问题。 - tom10271

1
多年过去了,这个仍然有效!请确保如果 $methodName 是用户定义的内容,则删除其中的空格。我之前无法让 $this->$methodName 正常工作,直到我注意到它有一个前导空格。

如果是用户定义的内容,请确保你不仅仅是修剪名称!例如......进行安全检查! ;) - Erk
在互联网上的某个地方,我详细介绍了如何将用户输入的utf8转换为Windows安全字符。QuickBooks让我经历了这个磨难 - 这就是为什么QB不再是我完成销售的一部分的原因... - Krista K
你真的允许客户端指定一个输入,动态调用一些方法吗?!我无言以对。 - Mcsky
显然要验证并检查类确实包含这样一个命名方法。有很多方法可以检查该值。它胜过冗长的 switch 语句。 - Snapey

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