在一个实例中设置匿名函数的 PHP 代码

7

我刚开始学习PHP,并且想知道是否有一种方法可以将匿名函数添加到类实例中。

例如,假设...

class A{
    public B;
}

$c = new A();

//This is where I am getting a little confused...
//The following wont work

$c->B = function(){echo('HelloWorld');};
$c->B();

我希望能够在许多不同的应用程序中重复使用相同的代码,使得我可以在特定情况下只需“交换”和替换函数。我正在使用php5.3(因此匿名函数应该可以工作,只是不是以我现在的方式)。非常感谢您的时间!-GK

你能详细介绍一下你正在尝试实现的这些不同应用程序吗?我认为简单的继承可能是更好的解决方案,但更多的信息会很有帮助。 - user142162
可能是重复问题:https://dev59.com/xnA85IYBdhLWcg3wHvo0 - dev-null-dweller
GK在这里, @Tim Cooper 我正在为我正在开发的游戏编写服务器端,该服务器将由数十个应用程序组成,这些应用程序将管理游戏的不同部分。它们都非常相似,并且使用许多相同的类,但是它们都需要执行自定义函数的能力...抽象我知道,谢谢你的帮助!@dev-null-dweller 我认为你是对的,我先尝试查找了这个问题,但显然我没有找得够仔细,谢谢! - geekay
7个回答

10
你可以使用__call魔术方法来完成这个任务。这样做不太美观,但是可以运行。像这样:
class A {
    public $B;

    public function __call($closure, $args)
    {
        call_user_func_array($this->$closure, $args);
    }
}

$c = new A();

$c->B = function () { echo('HelloWorld'); };
$c->B();

这里,我会去看看这个... 我需要弄清楚它是做什么的... 非常感谢你指引我正确的方向! - geekay
修改以撤销负评。我看到你发布了与user358390完全相同的解决方案(除了一个小差异),但我没有注意到时间是如此接近,所以我会给予怀疑的好处。 - Artefacto

5
我是一位有用的助手,可以为您翻译文本。

FWIW:

PHP 5.3 对匿名函数的处理很有趣。这样做不起作用:

$c->B = function() { echo func_get_arg(0); };
$c->B("This fails :(");

这将会起作用:

$c->B = function() { echo func_get_arg(0); };
$hilarious = $c->B;
$hilarious("This works!");

为了解决这个问题,您需要使用像 Oden提供的__call hack。这种行为在未来可能会发生变化。数组解引用RFC已经被最近提交到PHP的主干,并且该补丁引发了有关函数调用链接语法的讨论,其语法可能允许您执行所需操作而无需使用__call hack。不幸的是,在过去实现函数调用链式结构一直很困难

1
仅使用幽默方法有什么问题? - mukunda

4
# real ugly, but PoC...

class a {
  function __call($f, $x) {
    call_user_func_array($this->$f, $x);
  }
}

$a = new a;
$a->b = function() { echo "Hello world"; };
$a->b();

2

1
这不再是一个问题,PHP 7已经解决了它;
// no error
$result = ($this->anonFunc)();
$result = ($this->anonFunc)($arg1, $arg2, ...);

查看有关 AST 的更多信息。

1
你可以按照以下方式进行操作(这也适用于不是闭包的回调函数):
<?php
class A {
    private $fun;
    function setFun($fun) {
        if (!is_callable($fun))
            throw new InvalidArgumentException();
         $this->fun = $fun;
    }
    public function fun() {
        call_user_func_array($this->fun, func_get_args());
    }
}

$c = new A();

$c->setFun(function($a) { echo('HelloWorld ' . $a);});
$c->fun("here");

它返回这里是HelloWorld

话虽如此,您还应考虑继承或装饰者模式


0

与其将一个 __call 魔术方法挂钩到你的类中,你可以使用 call_user_func 直接执行可调用对象。

class A {
    public $b;
}

$c = new A();
$c->b = function(){echo('HelloWorld');};

call_user_func($c->b);    // HelloWorld

显然,如果PHP能够提供一些语法来直接执行这个操作,那将是非常好的。


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