Pregunta

¿Hay alguna manera de configurar devoluciones de llamada en (o registrar automáticamente) parámetros, entradas y salidas del método sin hacer llamadas explícitas dentro de cada método? Básicamente, quiero registrar esta información en mi clase de registrador (que es estática) sin tener que hacerlo manualmente para cada método.

En este momento tengo que llamar a Logger :: logEntry () y Logger :: logExit () en cada método para lograr esto. Me encantaría no tener que hacer esto:

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

        // Do some stuff...

        Logger::logExit();
    }
}
¿Fue útil?

Solución

usa una clase contenedora. Este método tiene los siguientes beneficios:

  • no es necesario cambiar las firmas de estructura / método de clase subyacentes
  • cambio de registro? solo actualiza esta clase
  • actualizar las llamadas a objetos en lugar de insertar código en cada clase que desee registrar

.

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

Otros consejos

Si desea hacer un registro de funciones por motivos de depuración, es posible que desee buscar en la extensión Xdebug. No hay una buena manera de interceptar llamadas de función en tiempo de ejecución, y cualquier intercepción automática agregará una gran sobrecarga de tiempo de ejecución.

Usando XDebug, podría activarlo según sea necesario, así como obtener muchas otras cosas

(XDebug se usa con PHPUnit para hacer pruebas de unidad y análisis de cobertura).

El problema con __call

__call puede parecer una solución divertida para el problema, pero hay 3 problemas con esto, a saber

  • Gastos generales de ejecución significativos. estás haciendo __call - > call_user_func_array, que literalmente agregará no una, sino dos llamadas de función a cada ejecución.

  • Los retrocesos se vuelven indescifrables: la función real que intentaba llamar se pierde en un mar de __call y call_user_func_array, lo que hace que el retroceso sea extremadamente difícil, especialmente si sus retrocesos incluyen sus listas de argumentos.

  • Estúpidas funciones ocultas: vas a volver al estilo PHP4 "ocultar" de funciones al prefijarlas con _ para detener al usuario que lo llama o lo ve directamente, porque si el nombre de la función se llama como quiere, la llamada __call no se activará, por lo que ya tiene una clase completa llena de cosas realmente horribles nombres de funciones, que los desarrolladores se verán tentados a llamar directamente de todos modos en varios lugares. (¡Y si desea deshacerse de __call más tarde, tendrá que cambiar el nombre de todas estas funciones para no romper el código!)

Por lo tanto, si está utilizando un código php para implementar esto dará como resultado un código épicamente horrible, con el que cualquier futuro usuario de su base de código NO querrá trabajar. Es mucho mejor obtener algo (como Xdebug) que se pueda agregar de forma transparente cuando lo necesite y ahorre mucho contaminando su código.

puedes usar la función mágica __call . Se llama cuando ninguna función coincide con ese nombre. Cambie el nombre de sus métodos para que tengan el prefijo de algo (por ejemplo, guión bajo) y, opcionalmente, configúrelos como privados / protegidos.

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"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top