繁体   English   中英

PHP:类方法的进入/退出回调?

[英]PHP: Callback on Entry/Exit of Class Methods?

有没有一种方法可以在方法参数,条目和出口上设置回调(或自动记录),而无需在每个方法中进行显式调用? 我基本上想将此信息记录到我的logger类(静态)中,而不必为每个方法手动进行处理。

现在,我必须在每种方法中调用Logger :: logEntry()和Logger :: logExit()来完成此操作。 我希望不必这样做:

class TestClass {
    public function tester($arg) {
        Logger::logEntry();
        Logger::info('Parameter $arg => ' . $arg);

        // Do some stuff...

        Logger::logExit();
    }
}

使用包装器类。 此方法具有以下优点:

  • 无需更改基础类结构/方法签名
  • 更改日志记录? 只需更新此课程
  • 更新对象调用与将代码插入要记录的每个类中

class LogWatch {
    function __construct($class)    {
        $this->obj  =   $class;
    }

    function __call($method, $args) {
        if (in_array($method, get_class_methods($this->obj) ) ) {
            Logger::logEntry();
            Logger::info('Parameter '.implode(', ', $args) );

            call_user_func_array(array($this->obj, $method), $args);

            Logger::logExit();

        } else {
            throw new BadMethodCallException();
        }
    }
}

$test = new LogWatch(new TestClass() );
$test->tester();

// you can use instances of `LogWatch()` just like your watched class
// including passing appropriate params:
$test->tester($param1, $param2);

如果为了调试而进行函数记录,则可能需要研究Xdebug扩展。 没有在运行时拦截函数调用的好方法,任何自动拦截都会增加巨大的运行时开销。

使用XDebug,您可以根据需要将其打开,以及获取许多其他内容

(因此,XDebug与PHPUnit一起用于进行单元测试和覆盖率分析。)

__call的问题

__call看起来可能是一个有趣的解决方案,但是这样做有3个问题,即

  • 执行开销很大。 您正在执行__call-> call_user_func_array,这实际上不会在每个执行中添加一个,而是两个函数调用。

  • 回溯变得难以理解:您试图调用的实际函数在__call和call_user_func_array的海洋中迷路了,从而使回溯变得异常困难,特别是如果回溯中包含了他们的争论列表。

  • 愚蠢的隐藏函数:您将返回PHP4样式的“隐藏”函数,在函数前面加上_来阻止用户直接调用或查看它,因为如果函数名碰巧被命名为__call,不会触发,因此您已经有了一个充满了真正可怕的函数名称的整个类,开发人员将很想在任何地方直接调用它们。 (并且,如果您以后想摆脱__call,则必须重命名所有这些函数,以免破坏代码!)

因此,如果你正在使用的PHP代码来实现,这将导致epically可怕的代码,该代码库中的任何未来的用户将不会想工作。 您最好获得可以在需要时透明添加的东西(例如Xdebug),并节省大量污染您的代码。

您可以使用魔术函数__call 没有函数匹配该名称时将调用该函数。 重命名您的方法,使其带有前缀(例如,下划线),并可以选择将其设置为私有/受保护。

class TestClass {
    public function __call($function, $args) {
        Logger::logEntry();
        Logger::info('Parameters: ' . implode(", ", $args);

        $localFunc = "_" . $function;
        $return = $this->$localFunc($args);

        Logger::logExit();

        return $return;
    }

    private function _tester() {
        // do stuff...
        return "tester called";
    }
}

 $t = new TestClass();
 echo $t->tester();
 // "tester called"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM