在类中调用函数时触发事件

时间:2013-06-04 15:53:28

标签: php class function events

PHP可以在调用类中的函数时触发事件,而不将其添加到类中的每个函数中吗?

示例:

<?php
    class A {
        function xxx() {
            //this function will be called everytime I call another function in this class  
        }

        public static function b() {
            return 'Hello Stackoverflow!';
        }

        public static function c() {
            //I also want this function to trigger the event!
        }
    }

    echo A::b();
?>

4 个答案:

答案 0 :(得分:12)

AFAIK没有本地语言结构。如果您需要它用于调试目的,我建议您深入了解xdebug扩展,尤其是function traces(太棒了!:)

另一个想法是在你的类中实现__call()并包装所有公共方法。但这需要更改代码并产生其他副作用:

(简化示例)

class Test {

    protected $listeners;

    public function __construct() {
        $this->listeners = array();
    }

    private function a() {
        echo 'something';
    }

    private function b() {
        echo 'something else';
    }

    public function __call($fname, $args) {
        call_user_func_array(array($this, $fname), $args);
        foreach($this->listeners as $listener) {
            $listener->notify('fname was called');
        }
    }

    public function addListener(Listener $listener) {
        $this->listeners[]= $listener;
    }
}

 class Listener {

     public function notify($message) {
         echo $message;
     }

 }

示例:

 $t = new Test();
 $l = new Listener();
 $t->addListener($l);

 $t->a();

答案 1 :(得分:3)

这是面向方面编程(AOP)的经典任务。 PHP没有对AOP的本机支持,但是,有一些框架可以使PHP中的AOP成为可能。其中之一是GO! AOP PHP framework。您还可以使用runkit实现AOP。

答案 2 :(得分:0)

您需要PHP SplObserver:From PHP Doc

答案 3 :(得分:0)

这是依赖注入和延迟初始化的经典任务!依赖是MySQL连接。因为它首先需要在执行第一个查询时可用,所以不需要在&#34; startup&#34;中进行初始化,但仅限于此。这称为延迟初始化,其实现极其简单:

class DbStuff {
  private $__conn = NULL;

  protected function _getConn() {
    if ( is_null( $this->__conn ) {
      $this->__conn = ... ;  // init (MySQL) DB connection here
      // throw on errors!
    }
    return $this->__conn;
  }

  public function someQuery($arg1, $arg2) {
    $conn = $this->_getConn();
    // MySQL query here:
    ...
  }
}

所有&#34;重构&#34;必需的是在每个查询方法中调用$this->_getConn()

面向方面编程不是解决此问题的工具,因为数据库连接是查询的固有依赖关系,而不是它的一个方面。自动记录所有执行的查询都是一个方面。

围绕PHP __call()构建的触发器也不是一个好选择;除了淘汰现代IDE的检查 - 很快就能很快看到模块是否正常 - 这会使测试变得更加复杂:受保护的$this->_getWhatever()很容易被覆盖在测试外观对象中 - 来自于要测试的类 - 返回模拟对象或其他任何东西。对于__call(),需要更多代码用于相同的目的,这会导致代码中出现错误的风险,这些代码仅用于测试(并且应该完全没有错误)