1

私はクラスを持っています:

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

ここで、すべての操作をログに記録するとします。Logger::add();内部のようなものを入れたくaddnewnumber()ありません-おそらくそのクラスを変更することはできません。それを解決する方法は?

4

2 に答える 2

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);

実際の動作をご覧ください

ただし、このアプローチにはいくつかの欠点があります。

  • 特定のタイプのオブジェクトを期待するコードでは機能しません(のProxy代わりに渡しますPhone
  • ラップされたクラスの非公開メンバーにアクセスすることはできません
于 2012-12-05T11:46:10.690 に答える
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 に答える