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.
la source
4.something
?__call()
pour faire du routage dynamique, est-il vraiment déraisonnable de s'attendre à ce que quelque part sur la piste, quelqu'un veuille gérer le cas où cela échoue? En tout cas, cela tourne en rond, donc ce sera mon dernier commentaire. Faites ce que vous voulez, en fin de compte, cela revient à un appel au jugement: un meilleur soutien par rapport à la cohérence. Les deux méthodes auront le même effet sur l'application en cas d'absence de manipulation particulière.Je vais jeter mon opinion d'opinion, mais si vous utilisez
trigger_error
n'importe où, vous faites quelque chose de mal. Les exceptions sont la voie à suivre.Avantages des exceptions:
Répondre à vos préoccupations, appeler une méthode qui n'existe pas peut être une possibilité valable . Cela dépend entièrement du contexte du code que vous écrivez, mais il peut arriver que cela se produise dans certains cas. Pour répondre à votre cas d'utilisation exact, certains serveurs de base de données peuvent autoriser certaines fonctionnalités que d'autres ne permettent pas. L'utilisation de
try
/catch
et des exceptions dans__call()
vs. une fonction pour vérifier les capacités est un tout autre argument.Le seul cas d'utilisation auquel je peux penser
trigger_error
est pourE_USER_WARNING
ou inférieur. Déclencher unE_USER_ERROR
bien est toujours une erreur à mon avis.la source
trigger_error
dans le contexte de __call ou __callStatic imite le comportement par défaut de la langueNoMethodError
que vous pouvez attraper si vous le souhaitez. Les erreurs sont une erreur géante en PHP à mon avis personnel. Ce n'est pas parce que le noyau utilise une méthode cassée pour signaler des erreurs que votre propre code devrait l'être.Les erreurs PHP standard doivent être considérées comme obsolètes. PHP fournit une classe intégrée ErrorException pour convertir les erreurs, avertissements et notifications en exceptions avec une trace de pile appropriée. Vous l'utilisez comme ceci:
En utilisant cela, cette question devient théorique. Les erreurs intégrées déclenchent désormais des exceptions et votre propre code devrait également l'être.
la source
E_NOTICE
s en exceptions. Ce serait mauvais.OMI, c'est un cas d'utilisation parfaitement valable pour
trigger_error
:En utilisant cette stratégie, vous obtenez le
$errcontext
paramètre si vous le faites$exception->getTrace()
dans la fonctionhandleException
. Ceci est très utile à certaines fins de débogage.Malheureusement, cela ne fonctionne que si vous utilisez
trigger_error
directement à partir de votre contexte, ce qui signifie que vous ne pouvez pas utiliser une fonction / méthode wrapper pour alias latrigger_error
fonction (vous ne pouvez donc pas faire quelque chose commefunction debug($code, $message) { return trigger_error($message, $code); }
si vous voulez les données de contexte dans votre trace).Je cherchais une meilleure alternative, mais jusqu'à présent je n'en ai pas trouvé.
la source