Ich habe eine Debatte mit einem Kollegen über den korrekten Gebrauch (falls vorhanden) von trigger_error
im Zusammenhang mit magischen Methoden . Erstens denke ich, dass trigger_error
dies bis auf diesen einen Fall vermieden werden sollte .
Angenommen, wir haben eine Klasse mit einer Methode foo()
class A {
public function foo() {
echo 'bar';
}
}
Nehmen wir nun an, wir möchten die exakt gleiche Schnittstelle bereitstellen, verwenden jedoch eine magische Methode, um alle Methodenaufrufe abzufangen
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
Beide Klassen reagieren auf die gleiche Weise foo()
, unterscheiden sich jedoch beim Aufrufen einer ungültigen Methode.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Mein Argument ist, dass magische Methoden aufgerufen werden sollten, trigger_error
wenn eine unbekannte Methode abgefangen wird
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;
}
}
}
Damit verhalten sich beide Klassen (fast) identisch
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Mein Anwendungsfall ist eine ActiveRecord-Implementierung. Ich benutze __call
, um Methoden zu fangen und zu handhaben, die im Wesentlichen dasselbe tun, aber Modifikatoren wie Distinct
oder haben Ignore
, z
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
oder
insert()
replace()
insertIgnore()
replaceIgnore()
Methoden wie where()
, from()
, groupBy()
usw. sind hartcodiert.
Mein Argument wird hervorgehoben, wenn Sie versehentlich anrufen insret()
. Wenn meine aktive Datensatzimplementierung alle Methoden fest codiert, wäre dies ein Fehler.
Wie bei jeder guten Abstraktion sollte der Benutzer die Implementierungsdetails nicht kennen und sich ausschließlich auf die Schnittstelle verlassen. Warum sollte sich die Implementierung, die magische Methoden verwendet, anders verhalten? Beides sollte ein Fehler sein.
quelle
4.something
?__call()
Sie dynamisches Routing verwenden, ist es wirklich so unvernünftig zu erwarten, dass irgendwo auf der Strecke jemand den Fall behandeln möchte, in dem dies fehlschlägt? Auf jeden Fall dreht sich das im Kreis, das wird mein letzter Kommentar sein. Tun Sie, was Sie wollen. Letztendlich kommt es auf ein Urteil an: Bessere Unterstützung versus Beständigkeit. Beide Methoden haben bei nicht spezieller Handhabung den gleichen Effekt auf die Anwendung.Ich werde meine Meinung da draußen äußern, aber wenn Sie
trigger_error
irgendwo verwenden, dann machen Sie etwas falsch. Ausnahmen sind der Weg zu gehen.Vorteile von Ausnahmen:
Das Aufrufen einer Methode, die nicht vorhanden ist, kann eine gültige Möglichkeit sein, um Ihre Bedenken auszuräumen . Dies hängt vollständig vom Kontext des Codes ab, den Sie schreiben. In einigen Fällen kann dies jedoch vorkommen. Unter Berücksichtigung Ihres genauen Anwendungsfalls können einige Datenbankserver Funktionen zulassen, die andere nicht zulassen. Die Verwendung von
try
/catch
und Ausnahmen in__call()
vs. einer Funktion zum Überprüfen von Funktionen ist ein völlig anderes Argument.Der einzige Anwendungsfall, an den ich denken kann,
trigger_error
ist fürE_USER_WARNING
oder niedriger. EinE_USER_ERROR
Obwohl auszulösen ist meiner Meinung nach immer ein Fehler.quelle
trigger_error
von __call oder __callStatic imitiert das Standardverhalten der SpracheNoMethodError
die Sie fangen können, wenn Sie dies wünschen. Fehler sind meiner Meinung nach ein riesiger Fehler in PHP. Nur weil der Core eine kaputte Methode zum Melden von Fehlern verwendet, sollte Ihr eigener Code dies nicht bedeuten.Standard-PHP-Fehler sollten als veraltet angesehen werden. PHP bietet eine integrierte Klasse ErrorException zum Konvertieren von Fehlern, Warnungen und Hinweisen in Ausnahmen mit einer vollständigen ordnungsgemäßen Stapelverfolgung. Du benutzt es so:
Damit wird diese Frage streitig. Eingebaute Fehler lösen jetzt Ausnahmen aus, und Ihr eigener Code sollte dies auch tun.
quelle
E_NOTICE
s keine Ausnahmen werden. Das wäre schlimm.IMO, dies ist ein perfekter Anwendungsfall für
trigger_error
:Mit dieser Strategie erhalten Sie die
$errcontext
Parameter, wenn Sie dies$exception->getTrace()
innerhalb der Funktion tunhandleException
. Dies ist für bestimmte Debugging-Zwecke sehr nützlich.Leider funktioniert dies nur, wenn Sie
trigger_error
direkt aus Ihrem Kontext verwenden. Dies bedeutet, dass Sie keine Wrapper-Funktion / -Methode verwenden können, um dietrigger_error
Funktion als Alias zu verwenden (Sie können also nichts tun,function debug($code, $message) { return trigger_error($message, $code); }
wenn Sie die Kontextdaten in Ihrem Trace haben möchten).Ich habe nach einer besseren Alternative gesucht, aber bisher keine gefunden.
quelle