doucheng4094
2015-03-24 06:23
浏览 89
已采纳

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

I have the following class in PHP with all static methods:

class Foo {
    public static function a {
    }

    public static function b {
    }

    public static function c {
    }

    public static function d {
    }

    public static function e {
    }
}

Is there a way to create a hook to fire before calling any of the methods in class Foo i.e. like a before hook? I need some logic, and don't want to have to add that logic to every static function like:

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();
    }
}

图片转代码服务由CSDN问答提供 功能建议

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

 <  code> class Foo {
 public static function a {
} 
 
 public static function b {
} 
 
 public static function c {
} 
 
 public static function d {
  } 
 
公共静态函数e {
} 
} 
   
 
 

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

  class Foo {
 private static function init(){
  //预逻辑
} 
 
公共静态函数a {
 Foo :: init(); 
} 
 
公共静态函数b {
 Foo :: init(); 
}  
 
公共静态函数c {
 Foo :: init(); 
} 
 
公共静态函数d {
 Foo :: init(); 
} 
 
公共静态函数e  {
 Foo :: init(); 
} 
} 
   
 
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • doubei8541 2015-03-24 06:44
    已采纳

    What you want is called an Aspect-Oriented Programming. It allows to define an advice before method call, property access, class initialization, etc.

    However, this technique is not used widely in PHP due to its complexity. I can suggest your an example with 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
        }
    }
    

    Visit http://demo.aopphp.com/?showcase=loggable for demo (see LoggingDemo::runByName() static method intercepted)

    点赞 评论
  • dousuitang5239 2015-03-24 06:34

    I guess you can use __callStatic() magic method to achieve.

    public static function __callStatic($name, $arguments)
    {
       // pre logic here 
       switch($name)
       { 
           case 'a':
           // do something
           break;
    
           case 'b':
           // do something
           break;
       }
    }
    
    点赞 评论
  • duangai1916 2015-03-24 06:40

    Basic answer: no, there is no such thing in plain PHP.

    However, you can try several options:

    1. You can call your methods like aSomeSuffix, bSomeSuffix, etc., and call them via __callStatic method computing that suffixed name on-the-fly.
      Pros:

      • Single handler

      Cons:

      • Your IDE won't see those methods until you explicitly write them down via phpDoc
      • Extra work and big pile of places to make a mistake (arguments passing by reference, missing method handling, etc.)
    2. You can try Go library that introduces aspect-oriented programming in PHP claims to be able to intercept static calls. I've never used it (though i've heard lots of good responses about it) and don't know anything about performance drops and/or caveats using it, but it seems to be matching your case. I guess, this would still require to write an annotation for every method, but it will result in single handler.

    3. Call initialization method in every method. This is what you're trying to avoid and not an option, i guess, just because it's violates DRY.

    点赞 评论
  • douzuo0002 2018-07-16 05:58

    It's a bit late to answer the question but here is a method I use:

    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();
        }
    }
    

    Now if you try something like Foo::a() since a is protected __callStatic is being called and you can provide hooks there. Also note that using static::class allow us to use Wrapper as a general class.

    点赞 评论

相关推荐 更多相似问题