php钩子加反射实现aop

  自从我了解了钩子以后就一直在想一个东西,就是调用一个全局变量,然后就自动调用一个方法,然后我就在网上各种找资料,没有找到哪怕是一个相关的;

  后面我仔细解剖了下这个需求,其实就两点要点:

    1:要调用的这个全局变量要各种处理好了的

    2:在这个方法中只会调用一次,而不是每次调用都调用这个方法

  想通这两点后我首先想到了的就是钩子,钩子会在加载方法前先调用,符合这两点,但是有个很大的限制,就是只能勾指定方法,当我要用多个方法的时候就显得很无力了,我总不能说每个方法我都写一个专有的钩子方法或专有的钩子吧,这太麻烦我就放弃了;

  后面我就想到了注解,把要调用的方法写在注解中,然后通过反射区读取注解,读取到注解就简单了,就可以通过钩子去勾对应的方法了;

  我用的是thinkphp5 所以我实例代码就用这个环境来写的

  首先是要调用全局变量的方法

  

/**
* @Annotation (aid,id)

* 上面括号里面可以放多个,以“,”隔开
*/

public function get(){

  $this->id;

  $this->aid;

}

然后我的钩子是放在父类的id和aid可以在父类定义,用于全局

/**
* 钩子加反射实现aop
*/
protected function hook()
{
  $request= Request::instance();
  $controller = explode('.', $request->controller());
  $action = $request->action();

  $controller = !is_array($controller) ? $controller : $controller[count($controller)-1];


  //判断类是否存在,防止要实例的类不在这个命名空间
  if(class_exists($controller)) return;

  //判断类中是否有指定方法,由于是放在父类所以我用的是$this,但是在不是父类的方法中就放 new $controller()
  if(!method_exists($this, $action)) return;

  //获取反射,由于是放在父类所以我用的是$this,但是在不是父类的方法中就放 new $controller()
  $re = new \ReflectionClass($this);

  //获取注解
  $comment = $re->getMethod($action)->getDocComment();
  preg_match_all('/@Annotation\s+\((.*)\)/', $comment, $data);

  $annotation = $data[1][0];

  //有值的时候就执行
  if(strlen($annotation) != 0)
  {
    $annotation = explode(',', $annotation);
    foreach ($annotation as $k => $v)
    {
      //判断类中是否有指定的方法,由于是放在父类所以我用的是$this,但是在不是父类的方法中就放 new $controller()
      if(method_exists($this, $v))
      {
        $this->$v();
      }
    }
  }
}

然后就在构造方法中调用

public function _initialize()
{
  $this->hook();
}

写在最后

  有一点要注意,检测到类中没有要勾的方法是不会执行对应的方法的;

  肯定会有人想不到运用场景,这个的运用场景是非常广泛的,就比如说以往我们接收到id后都要先各种判断,然后才敢用这个id,如果这时候这些判断这些先封装成一个类,然后用我这个方法调用,不就可以直接用了呀

  然后也会有人说都封装成一个类了直接用$this调用不就好了,我会告诉他简单几个是很简单,但是有很多呢,就会有一大串,看起来很不舒服然

猜你喜欢

转载自www.cnblogs.com/zhangzhaowen/p/11763270.html