Estoy teniendo un debate con un colega sobre el uso correcto (si corresponde) de trigger_error
en el contexto de métodos mágicos . En primer lugar, creo que se debe evitar trigger_error
excepto para este caso.
Supongamos que tenemos una clase con un método foo()
class A {
public function foo() {
echo 'bar';
}
}
Ahora digamos que queremos proporcionar la misma interfaz pero usar un método mágico para capturar todas las llamadas a métodos
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
}
}
}
$a = new A;
$b = new B;
$a->foo(); //bar
$b->foo(); //bar
Ambas clases son iguales en la forma en que responden a foo()
pero difieren cuando se llama a un método no válido.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Mi argumento es que los métodos mágicos deben llamar a trigger_error
cuando se detecta un método desconocido
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
default:
$class = get_class($this);
$trace = debug_backtrace();
$file = $trace[0]['file'];
$line = $trace[0]['line'];
trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
break;
}
}
}
Para que ambas clases se comporten (casi) de forma idéntica
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Mi caso de uso es una implementación de ActiveRecord. Uso __call
para capturar y manejar métodos que esencialmente hacen lo mismo pero tienen modificadores como Distinct
o Ignore
, por ejemplo,
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
o
insert()
replace()
insertIgnore()
replaceIgnore()
Los métodos como where()
, from()
, groupBy()
, etc. están codificados.
Mi argumento se resalta cuando llama accidentalmente a insret()
. Si mi implementación de registro activo codificara todos los métodos, sería un error.
Al igual que con cualquier buena abstracción, el usuario debe desconocer los detalles de la implementación y confiar únicamente en la interfaz. ¿Por qué la implementación que utiliza métodos mágicos debería comportarse de manera diferente? Ambos deben ser un error.