PHP: Sınıf Yöntemler Entry / Exit Callback?

3 Cevap php

Ben geri çağrıları kurmak (veya automataically log) her yöntem içinde açık çağrı yapmadan yöntem parametreleri, girişleri ve çıkışları bir yolu var mı? Ben temelde her yöntem için elle yapmak zorunda kalmadan (statik) benim logger sınıfına bu bilgileri oturum istiyorum.

Şu anda bunu gerçekleştirmek için her yöntemi Logger :: logEntry () ve Logger :: logExit () aramak zorunda. Bunu yapmak zorunda değildir isterdim:

class TestClass {
    public function tester($arg) {
        Logger::logEntry();
        Logger::info('Parameter $arg => ' . $arg);

        // Do some stuff...

        Logger::logExit();
    }
}

3 Cevap

sarıcı sınıfını kullanın. Bu yöntem şu faydaları vardır:

  • bu temel sınıf yapısı / yöntem imzaları değiştirmek gerek
  • günlüğü değiştirebilir? sadece bu sınıf güncellemek
  • güncelleme nesne oturum istediğiniz her sınıfa kodu ekleyerek vs çağırır

.

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

Eğer hata ayıklama uğruna fonksiyon günlüğe yapmak istiyorsanız Xdebug uzantısı içine bakmak isteyebilirsiniz. Orada zamanında at fonksiyon çağrıları önünü iyi yolu, ve herhangi bir otomatik durdurma büyük zamanı yükü katacak.

Yerine gerektiği gibi-onu açmak, hem de diğer sürü alabilir XDebug kullanma

(XDebug dolayısıyla birim test ve kapsama analizi yapmak PHPUnit ile kullanılır.)

The Problem with __call

__call soruna eğlenceli bir çözüm olarak görünebilir, ancak bu ile 3 sorunları vardır, yani

  • Önemli Yürütme Tepegöz. senin yaptığını __ çağrı - anlamıyla birini değil katacak> call_user_func_array, ama two fonksiyonu her yürütme çağırır.

  • Backtraces çözülemez hale: Aramaya çalıştığınız gerçek işlev __ sizin backtraces onların arguent listeleri ile gelen, özellikle çağrı ve son derece sert Backtracing yapma call_user_func_array dahil bir denizde kaybolur.

  • Aptal Gizli Fonksiyonlar: Sen onu arayarak ya da görerek doğrudan kullanıcıyı durdurmak için _ ile önek tarafından işlevlerin "gizleme" Geri PHP4 tarzı gidiyoruz çünkü işlev adı, onlar istemek ne adlandırılacak olursa __ çağrı Tetiği alışkanlık, böylece zaten geliştiriciler çeşitli yerlerde zaten doğrudan aramak için cazip olacak gerçekten korkunç işlev adları, dolu bir sınıf var. (Daha sonra __ çağrı kurtulmak istiyorsanız eğer, kodu kırmak değil gibi tüm bu işlevleri yeniden adlandırmak zorunda kalacak!)

Böylece, bu uygulamak için php kodu kullanan eğer kod temeli gelecekteki herhangi bir kullanıcı NOT ile çalışmak istiyoruz ki, epically korkunç koda neden olur. Sen çok daha iyi bunu gerektiğinde şeffaf eklenebilir (Xdebug gibi) bir şey almak, ve kodunuzu kirletici ölçüde tasarruf edilir.

Eğer sihirli işlevi __call kullanabilirsiniz. Hiçbir fonksiyon bu ismi aynı zaman çağrılır. Metodlar şey, önek yeniden adlandırın (örneğin: çizgi), ve isteğe bağlı özel / korunan bunları.

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"