PHP类:每次调用方法时调用特定函数

3
我希望能够在PHP中每次调用方法时调用一个函数。
例如:
$a = new a();
$a->function1();

这将会调用两个函数:basicFunction()function1()

对于该类的任何后续方法调用,情况都是相同的。在面向对象的PHP中是否可能实现这一点?


不清楚您是想在调用function1时还是在构造函数被调用时或者在任何函数被调用时调用basicFunction。此外,basicFunction是否是a类的一部分?请澄清问题,并可能添加一个具体的示例来说明您需要这个功能的原因。 - Gordon
5个回答

6
最简单的方法就是直接调用该方法。
public function function1 {
    $this->basicFunction();
    // …
}

你可能需要的是像面向切面编程这样的东西。然而,在PHP中这并不常见。最显著的用途是在Flow3框架中。
对于其他更常见的可用于PHP OOP的方法,请查看以下内容: 这些可以让你在运行时添加任意行为和控制流程。
(元) 顺便说一句,我们真的需要四个答案建议使用__call吗?我建议各位回答者回顾一下自己的答案,梳理出微小的差异,并协商出最佳答案。其他三个人可以撤回他们的答案。

3

在PHP中没有类似这样的功能。但是,您可以使用魔术方法__call()来模拟此行为:

class YourClass {
    public function __call($method, $args){
        // do what you want to do everywhere (i.e. call your basicFunction)
        return call_user_func_array(array($this, 'base'.ucfirst($method)), $args);
    }

    private baseSomeFunction() {
        // ...
    }
}

使用方法:

$obj = new YourClass();
$obj->someFunction(); // this calls baseSomeFunction and executes the code
                      // in the __call() method

将你的“魔术”方法前缀添加类似于base的内容,可以确保没有人能够调用你的私有函数,并将此访问限制仅限于已添加前缀的函数。你应该根据自己的需要更改这个前缀。


3
当然可以,虽然这会涉及一些额外的开销。魔术方法_call可以处理不存在的方法,所以你可以这样做:
class myClass {
    public function __call($name, $arguments) {

        $this->doSomething();
        $this->$name($arguments);
    }

    private function calledmethod() { ... }

然后您将调用:

$class->calledmethod();

由于方法calledmethod不是公共的,所以调用_call方法会运行您的“基本”方法,然后运行calledmethod

我觉得有必要问一下,为什么你需要这样做?如果您描述实际要解决的问题,可能会有更优雅的解决方案。


这不会返回函数的输出。 - cypher
1
@elusive: 已修复,最近使用了太多js,谢谢。@cypher: OP从未提到要返回一个值。 - Erik
@Erik:在JavaScript中,变量名可以使用“-”吗?我不知道。我知道你可以像这样使用任何字符串:window['some-function-name'](),但那会有点麻烦,对吧? - jwueller
这会使得所有私有方法都变成公有的。 - jwueller
还有第二个问题:参数被作为数组而不是普通参数传递。 - jwueller
显示剩余2条评论

0

你必须使用__call魔术方法 以你的例子为例:

class Foo{
    public function __call($method_name, $arguments){
        $this->basicFunction();
        return call_user_func_array(array($this, $method_name), $arguments);
    }


    private function basicFunction(){}
    protected function function1(){}
}

1
如果function1()是公共的,__call将不会被使用。 - StasM
现在我可以调用 每个 私有方法。 - jwueller

0

使用__call魔术方法,像这样:

class a {
  private function function1() { ... }
  public function __call($name, $args) {
       /* do stuff */;
       return call_user_func_array(array($this, $name), $args);
  }
}

请注意,如果从类的内部调用function1(),则此方法不起作用。那么您就需要重新命名function1()并使用不同的名称进行调用。思路是仅在找不到函数或无法查看函数时才调用__call。

1
我可以调用这个类的每一个私有函数。 - jwueller
1
@elusive - 如果你对此感到困扰,可以在__call中加入一些条件。这只是一个建议,不是生产代码 :) - StasM

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