簡體   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