我有一堂课:
class Phone
{
    public function addnewnumber ($name, $number)
    {
    }
}
现在让我们假设我想记录所有操作。我不想在Logger::add();里面放一些东西addnewnumber()——也许不可能修改那个类。那怎么解决呢?
我有一堂课:
class Phone
{
    public function addnewnumber ($name, $number)
    {
    }
}
现在让我们假设我想记录所有操作。我不想在Logger::add();里面放一些东西addnewnumber()——也许不可能修改那个类。那怎么解决呢?
您不能在每个类的每个方法上自动调用某些日志记录功能。如果你想在手机的 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 方法时,它会记录号码,然后调用实际方法。
在某些情况下,您可以使用一个代理类来包装您的对象并允许您使用__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);
但是,这种方法确实有一些缺点:
Proxy而不是 a Phone)