J'ai un débat avec un collègue sur l'utilisation correcte (le cas échéant) de trigger_error
dans le contexte des méthodes magiques . Premièrement, je pense que cela trigger_error
devrait être évité, sauf dans ce cas.
Disons que nous avons une classe avec une méthode foo()
class A {
public function foo() {
echo 'bar';
}
}
Supposons maintenant que nous voulons fournir la même interface exacte, mais utilisons une méthode magique pour intercepter tous les appels de méthode
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
Les deux classes sont identiques dans la façon dont elles répondent, foo()
mais diffèrent lors de l'appel d'une méthode non valide.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Mon argument est que les méthodes magiques devraient appeler trigger_error
lorsqu'une méthode inconnue est interceptée
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;
}
}
}
Pour que les deux classes se comportent (presque) de manière identique
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Mon cas d'utilisation est une implémentation ActiveRecord. J'utilise __call
pour attraper et gérer des méthodes qui font essentiellement la même chose mais qui ont des modificateurs comme Distinct
ou Ignore
, par exemple
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
ou
insert()
replace()
insertIgnore()
replaceIgnore()
Des méthodes telles que where()
, from()
, groupBy()
, etc. sont codés en dur.
Mon argument est mis en évidence lorsque vous appelez accidentellement insret()
. Si mon implémentation d'enregistrement actif codait en dur toutes les méthodes, ce serait une erreur.
Comme pour toute bonne abstraction, l'utilisateur doit ignorer les détails de mise en œuvre et se fier uniquement à l'interface. Pourquoi l'implémentation qui utilise des méthodes magiques devrait-elle se comporter différemment? Les deux devraient être une erreur.
4.something
?