使用类属性作为函数名称调用变量函数


Call a variable function using a class property as function name

以下代码使用存储在属性中的字符串"rand"$prop通过将 $function 用作临时局部变量来调用 rand() 作为变量函数。

class C
{
    private $prop = "rand";
    public function execute()
    {
        $function = $this->prop;
        echo $function();
    }
}
$c = new C();
$c->execute();

这有效,但我需要仅使用一个语句调用存储在 $this->prop 中的变量函数并避免使用临时变量。

我没有运气

echo $this->prop();

因为它实际上调用了不存在的方法 prop(),无论如何它都不是我想做的。

由于 $this->prop 实际上是一个字符串,我尝试了以下内容,但它会产生语法错误:

echo ($this->prop)();

我也试过

echo call_user_func($this->prop);

虽然它可以完成工作,但它对我来说不是一个选择,因为它不是一个可变函数。

似乎变量函数

只能使用局部变量作为函数名称。

有没有人知道一种使用类属性作为函数名称直接调用变量函数的方法,避免局部临时变量和 call_user_func() 的使用?

编辑:我理解你的困惑,因此我将解释使用call_user_func有什么问题。

我只是在探索变量函数提供的机会,这似乎比变量提供的机会要少。

让我们尝试使用变量变量作为最简单的形式。

假设我们有一个函数 f(),它返回字符串 "something"

function f() {
  return "something";
}

然后是一个包含字符串"something"的类属性

$this->prop = "something";

$something是局部变量

$something = "I am a local variable";

然后,以下所有语句都将起作用:

$r = ${"something"};
$r = ${$this->prop};
$r = ${f()};

我个人的结论是:不管字符串"某物"是如何获得的;只需用大括号{}包围它,并在前面加上一个美元符号$,以将其视为变量。漂亮的弗莱西贝。

让我们对变量函数尝试相同的操作

现在我们有一个函数 f(),它返回字符串 "rand"

function f() {
  return "rand";
}

然后是一个包含字符串"Rand"的类属性

$this->prop = "rand";

另一方面,变量函数不允许将后跟括号 () 的字符串视为函数调用。

$r = "rand"(); // Produces a syntax error, unexpected '()' after a string
$r = $this->prop(); // Calls the 'prop()' method, which does not exist
$r = f()(); // Again a syntax error, unexpected '()' after the function f()

我必须得出结论,变量函数总是需要运行局部变量:(

你需要实现一个魔术__call方法,如下所示:

class C
{
    private $prop = "execute";
    public function __call($method, $args)
    {
        if($method == "prop")  // just for this prop name
        {
            if(method_exists($this, $this->prop))
                return call_user_func_array([$this, $this->prop], $args);
        }
    }
    public function execute ($s){
        echo '>>'.$s.'<<';
    }        
}
$c = new C;
$c->prop(123);

这确实感觉像是PHP语法中的一个明显遗漏。(虽然从字面上看,我想它们是变量函数,而不是属性函数!?我可能希望以下"大括号"语法有效,但它没有,Parse error: syntax error, unexpected '{' in ....

echo {$this->prop}();

但是,与其他方法相比,使用可变函数语法具有显著的好处。变量函数比 call_user_func()/call_user_func_array() 更快,并且本机支持按引用传递,而不是带有 call_user_func_array() 的"特殊情况"调用时间按引用传递(在所有其他情况下均已弃用)。

__call魔术方法(上面)的另一种方法是简单地使用包装器方法,您将函数/方法名称传递给该方法并在该包装器方法中使用变量函数。

以最简单的形式:

function callUserFunc($callable) {
    return $callable();
}

由于性能优势(超过使用call_user_func_array()),一些框架实现了类似的"帮助程序"方法,允许可变数量的参数。另一个问题/答案更深入,涵盖了一些性能基准:使用显式参数调用函数与 call_user_func_array()

如果有人想知道,从 PHP 7 开始,我们得到了无限调用的函数表达式。

虽然此特殊情况未记录,但它实际上适用于以下示例:

class Test {
    private $func = "strtolower";
    public function testFunc() {
        return ($this->func)("ALPHABET");
    }
}
$t = new Test();
echo $t->testFunc(); //echoes alphabet in PHP 7+ error in anything below

这可以从 https://3v4l.org/JiuIF