在钩子之前,使用静态方法的PHP类


PHP class with static methods, before 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();
    }
}

您想要的被称为面向方面编程。它允许在方法调用、属性访问、类初始化等之前定义建议。

然而,由于其复杂性,该技术在PHP中没有得到广泛使用。我可以用Go给你举个例子!AOP框架。

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对于demo(请参阅LoggingDemo::runByName()static method intercepted)

我想你可以使用__callStatic()魔术方法来实现。

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

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

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

  1. 您可以调用您的方法,如aSomeSuffixbSomeSuffix等,并通过__callStatic方法实时计算后缀名称来调用它们
    优点:

    • 单个处理程序

    缺点:

    • 在通过phpDoc显式地写下这些方法之前,IDE不会看到这些方法
    • 额外的工作和大量出错的地方(引用传递的参数、缺少方法处理等)
  2. 您可以尝试在PHP中引入面向方面编程的Go库,该库声称能够拦截静态调用。我从未使用过它(尽管我听到了很多关于它的好回复),也不知道使用它会导致性能下降和/或注意事项,但它似乎与您的情况相匹配。我想,这仍然需要为每个方法编写一个注释,但这将导致单个处理程序。

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