有没有办法在不在每个方法中进行显式调用的情况下设置回调(或自动记录)方法参数,条目和出口?我基本上想要将这些信息记录到我的记录器类(这是静态的),而不必为每个方法手动执行。
现在我必须在每个方法中调用Logger :: logEntry()和Logger :: logExit()来完成此任务。我很乐意不必这样做:
class TestClass {
public function tester($arg) {
Logger::logEntry();
Logger::info('Parameter $arg => ' . $arg);
// Do some stuff...
Logger::logExit();
}
}
答案 0 :(得分:11)
使用包装类。这种方法有以下好处:
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);
答案 1 :(得分:5)
如果您想为了调试而进行功能记录,您可能需要查看Xdebug扩展。在运行时没有很好的方法来拦截函数调用,任何自动拦截都会增加很大的运行时开销。
使用XDebug你可以根据需要打开它,以及获得许多其他东西
(因此,XDebug与PHPUnit一起用于单元测试和覆盖率分析。)
__调用可能看起来是一个有趣的问题解决方案,但这有 3 问题,即
重大执行开销。你在做__call - > call_user_func_array,它实际上不会为每次执行添加一个,而是两个函数调用。
Backtraces变得无法解读:你试图调用的实际函数在__call和call_user_func_array的海洋中迷失,使得回溯变得非常困难,特别是如果你的回溯带有他们的arguent列表。
愚蠢的隐藏函数:你回到PHP4风格“隐藏”函数的前提是用_来阻止用户直接调用它或看到它,因为如果函数名恰好被命名为什么不,__ call不会触发,所以你已经有了一整套真正可怕的函数名称,开发人员很想在各个地方直接调用。 (如果你想在以后删除__call,你必须重命名所有这些函数,以免破坏代码!)
因此,如果您正在使用PHP代码来实现这将导致严重可怕的代码,您的代码库的任何未来用户将 NOT 想要使用。获得可以在需要时透明添加的东西(如Xdebug)要好得多,并且可以大大节省污染代码。
答案 2 :(得分:-1)
你可以使用魔术函数__call
。当没有函数匹配该名称时,它会被调用。将您的方法重命名为前缀(例如:下划线),并可选择将它们设置为private / protected。
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"