PHP类用静态方法,挂钩之前

时间:2015-03-24 06:23:11

标签: php class static hook

我在PHP中使用以下所有静态方法的类:

class Foo {
    public static function a {
    }

    public static function b {
    }

    public static function c {
    }

    public static function d {
    }

    public static function e {
    }
}

有没有办法在调用类Foo中的任何方法之前创建一个要触发的钩子,就像之前的钩子一样?我需要一些逻辑,并且不希望将逻辑添加到每个静态函数中,如:

class Foo {
    private static function init() {
        // pre logic here
    }

    public static function a {
        Foo::init();
    }

    public static function b {
        Foo::init();
    }

    public static function c {
        Foo::init();
    }

    public static function d {
        Foo::init();
    }

    public static function e {
        Foo::init();
    }
}

4 个答案:

答案 0 :(得分:3)

您想要的是Aspect-Oriented Programming。它允许在方法调用,属性访问,类初始化等之前定义建议。

然而,由于其复杂性,这种技术在PHP中并未得到广泛应用。我可以使用Go! AOP Framework建议您的示例。

class AutoInitializationAspect implements Aspect
{

    /**
     * This advice intercepts an execution of static methods
     *
     * We use "Before" type of advice to initialize the state
     *
     * @param MethodInvocation $invocation Invocation
     *
     * @Before("execution(public Foo::*(*))", scope="target")
     */
    public function beforeMethodExecution(MethodInvocation $invocation)
    {
        $class = $invocation->getThis(); // will be the class name
        $class::init(); // access to the private scope of class
    }
}

访问http://demo.aopphp.com/?showcase=loggable进行演示(请参阅截取的LoggingDemo :: runByName()静态方法)

答案 1 :(得分:0)

我猜你可以使用__callStatic()魔法来实现。

public static function __callStatic($name, $arguments)
{
   // pre logic here 
   switch($name)
   { 
       case 'a':
       // do something
       break;

       case 'b':
       // do something
       break;
   }
}

答案 2 :(得分:0)

基本答案:不,普通PHP中没有这样的东西。

但是,您可以尝试以下几种选择:

  1. 您可以调用aSomeSuffixbSomeSuffix等方法,并通过__callStatic方法计算,即动态添加名称。
    优点:

    • 单一处理程序

    缺点:

    • 在通过phpDoc
    • 明确写下这些方法之前,您的IDE不会看到这些方法
    • 造成错误的额外工作和大堆地方(通过引用传递参数,缺少方法处理等)。
  2. 您可以尝试在PHP声明中引入面向方面编程的Go库,以便能够拦截静态调用。我从来没有使用它(虽然我听过很多关于它的好的回答)并且对使用它的性能下降和/或警告一无所知,但它似乎与你的情况相符。我想,这仍然需要为每个方法编写一个注释,但它会导致单个处理程序。

  3. 在每种方法中调用初始化方法。这是你想要避免的,而不是一个选项,我猜,只是因为它违反了DRY。

答案 3 :(得分:0)

回答这个问题有点晚了,但这是我使用的一种方法:

class Wrapper {
    public static function __callStatic($name, $arguments) {
        //DoSomethingBeforeFunctionCall();
        call_user_func_array([static::class, $name], $args);
        //DoSomethingAfterFunctionCall();
    }
}

class Foo extends Wrapper{
    protected static function a() {
       //DoSomething();
    }

    protected static function b() {
       //DoSomething();
    }

    protected static function c() {
        //DoSomething();
    }

    protected static function d() {
        //DoSomething();
    }

    protected static function e() {
        //DoSomething();
    }
}

现在,如果您尝试使用类似Foo::a()之类的方法,因为a受保护,则会调用__callStatic,您可以在其中提供钩子。另外请注意,使用static::class可以使我们将Wrapper用作常规类。