1

我有一堂课:

class Phone
{
    public function addnewnumber ($name, $number)
    {
    }
}

现在让我们假设我想记录所有操作。我不想在Logger::add();里面放一些东西addnewnumber()——也许不可能修改那个类。那怎么解决呢?

4

2 回答 2

1

您不能在每个类的每个方法上自动调用某些日志记录功能。如果你想在手机的 addnewnumber 方法中添加日志记录,而不改变类本身,你可以在你自己的类中扩展它。

class Phone
{
    public function addnewnumber($name, $number)
    {
    }
    public function somethingelse()
    {
    }
}

class MyPhone extends Phone
{
    public function addnewnumber($name, $number)
    {
        Logger::Add();
        parent::addnewnumber($name, $number);
    }
}

现在您的 MyPhone 类具有所有电话方法,但是当调用 addnewnumber 方法时,它会记录号码,然后调用实际方法。

于 2012-12-05T11:32:18.543 回答
1

在某些情况下,您可以使用一个代理类来包装您的对象并允许您使用__call. 它看起来像这样:

class Proxy
{
    private $_target;
    public function __construct($target)
    {
        $this->_target = $target;
    }

    public function __call($name, $params)
    {
        $callable = array($this->_target, $name);
        if (!is_callable($callable)) {
            trigger_error('Call to undefined method '.
                           get_class($this->_target).'::'.$name, E_USER_ERROR);
        }

        return $this->dispatch($callable, $params);
    }

    protected function dispatch($callable, $params)
    {
        return call_user_func_array($callable, $params);
    }
}

然后,您可以从此类派生并覆盖dispatch以执行自定义处理:

class LoggingProxy extends Proxy
{
    protected function dispatch($callable, $params)
    {
        echo "Before calling ".get_class($callable[0]).'::'.$callable[1]."\n";
        $return = parent::dispatch($callable, $params);
        echo "After calling ".get_class($callable[0]).'::'.$callable[1]."\n";
        return $return;
    }
}

并像这样使用它:

$proxy = new LoggingProxy(new Phone);
$proxy->addnewnumber(1, 2);

看到它在行动

但是,这种方法确实有一些缺点:

  • 它不适用于需要某种类型对象的代码(您传递的是 aProxy而不是 a Phone
  • 它不允许您访问包装类的非公共成员
于 2012-12-05T11:46:10.690 回答