Catchen von DB-Exceptions?!

Das Forum soll der Ablage von Lösungen für immer wieder auftauchende Problemstellungen dienen. // This forum contains solutions to problems that frequently occur.
Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Catchen von DB-Exceptions?!

Beitrag von MrNiceGuy » 05.03.2011, 13:24:40

Moin!

Ich glaube, dass ich gerade auf dem Schlauch stehe, aber ich habe ein riesen Problem: Ich arbeite gerade an einem Setup-Script mit dem man die Datenbank-Verbindung einrichtet. Dabei habe ich nun folgendes Problem:

Wenn ich die Datenbank-Daten eingebe habe ich keine direkte Möglichkeit mit Hilfe des Connection-Managers diese Verbindung zu testen. Ich muss also manuell eine Instanz des entsprechenden Handlers aufrufen oder vorher die Daten in einer Konfiguration speichern, bevor ich über den ConnectionManager arbeiten kann. Nungut, egal, wie ich es mache: Wenn der User falsche Zugangsdaten eingegeben hat erhalte ich immer eine Exception, die am Browser ausgegeben wird. Nun aber das Kuriose: Ich will sie mit try/catch abfangen, nur scheint das nicht zu funkionieren!?

Code: Alles auswählen

    try
    {
      $oConnectionManager = $this->__getServiceObject
        ( 'core::database',
          'ConnectionManager'
         );

      $oConnection = $oConnectionManager->getConnection ('cms_db');
    }
    catch (Exception $oException)
    {
      // Hier der Code fürs Catch
    }


Der Code im Catch-Teil wird zwar ausgeführt,d ie Exception selbst aber trotzdem ausgegeben!? Mache ich hier einen Denkfehler? Ich komme jedenfalls nicht dahinter, wie ich die Ausgabe unterdrücken kann :(

Im Übrigen wäre es toll, wenn man eine Connection auch testen könnte, ohne die Konfiguration zu speichern. Das wäre mal eine Erweiterung des ConnectionManagers wert, nur leider kann man von diesen ja nicht ableiten (final) und selbst wenn nur bedingt auf die Elemente zugreifen (private). Wenn ich das manuell ändere ist beim nächsten Update wieder alles "falsch" :(

LG
Lutz
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.03.2011, 15:10:26

Hallo Lutz,

schön dich wieder öfter hier im Forum zu hören! :) War deine letzte Reise erfolgreich?

Ein Beispiel für Datenbank-Exceptions findest du in der Sandbox (1.13!) unter http://adventurephpfra.svn.sourceforge.net/viewvc/adventurephpfra/branches/php5/1.13/examples/sandbox/apps/sandbox/pres/controller/db_wizzard_controller.php?revision=1156&view=markup. Du kannst Exceptions einfach per

Code: Alles auswählen

try {
   ...
catch (DatabaseHandlerException $e) {
   ...

fangen.

Code: Alles auswählen

Der Code im Catch-Teil wird zwar ausgeführt,d ie Exception selbst aber trotzdem ausgegeben!? Mache ich hier einen Denkfehler? Ich komme jedenfalls nicht dahinter, wie ich die Ausgabe unterdrücken kann :(

Nutzt du den MySQLiHandler? Bei der mysqli-Extension gab es bereits in 1.13 einige kuriose Geschichten, dass keine Exception bei nicht erfolgreichen Verbindungen geworfen wurde. Das ist aber in 1.13 korrigiert. :roll:

Im Übrigen wäre es toll, wenn man eine Connection auch testen könnte, ohne die Konfiguration zu speichern. Das wäre mal eine Erweiterung des ConnectionManagers wert, nur leider kann man von diesen ja nicht ableiten (final) und selbst wenn nur bedingt auf die Elemente zugreifen (private). Wenn ich das manuell ändere ist beim nächsten Update wieder alles "falsch" :(

Hmm, das könnte man theoretisch dadurch erreichen, dass man ein Overloading der Methode getConnection() erreicht und dieser eine Instanz von Configuration übergibt. Mehr braucht der konkrete Treiber ja ohnehin nicht. Wäre eine Überlegung wert. Aber an sich kannst du dir ja mit 1.13 ohnehin einfacher damit behelfen, dass du die Konfiguration mit dem CM auch schreiben kannst. Lesen und schreiben wird dann (siehe Beispiel) zum Kinderspiel. :)
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Catchen von DB-Exceptions?!

Beitrag von MrNiceGuy » 06.03.2011, 16:42:13

Hi Christian!

Ja, es tut auch mir gut endlich wieder etwas Zeit für das APF zu haben :) Und meine letzte Reise war sehr erfolgreich, wenngleich diese auch schon ein bisschen zurückliegt und im Hafen-Becken von Kiel ein jehes Ende fand ;)

Aber zurück zum Thema: Ich habe gestern noch soweit rausgefunden, dass es offensichtlich keine Exception, sondern ein Error ist, der da angezeigt wird (also statt des Exception-Handlers wird der Error-Handler aktiviert). Darauf gekommen bin ich durch einen anderen Thread, wo jemand ein ähnliches Problem hatte und du dann meintest, dass der Missbrauch des ErrorHandlers für seine Zwecke eher unsauber wäre. Ich könnte aber offensichtlich durch einen eigenen ErrorHandler dafür sorgen, dass diese Meldung nicht ausgegeben wird, nur habe ich mich damit noch nicht neher befasst.

Meine eigentliche Intention wäre es auch eher eine Lösung für diesen Umstand zu finden, auch wenn ich da momentan noch ein bisschen wieder Ochse vor dem großen Tor stehe.

Der Ansatz der Überladung klingt ansich erstmal ganz nett, nur weiß ich gerade nicht, wie genau das gemeint ist. Ich schaue mir demnächst die Klassen nochmal genauer an, um nachvollziehen zu können, wie du das meintest. Aber meine Vermutung ist gerade - wo ich so drüber nachdenke - ob der Fehler nicht trotzdem ausgegeben würde, denn egal ob ich es schaffe mit einer Überladung die Konfigurations-Daten in den Datenbank-Treiber zu bekommen oder dieser sich die Daten vom ConnectionManager aus der Konfiguration laden lässt: Das Problem wird das Gleiche bleiben: Eine Fehlermeldung wegen falscher Zugangsdaten (wenn diese halt falsch sind). Ich muss also so oder so irgendwie verhindern, dass diese Daten ausgegeben werden...

Im Übrigen arbeite ich mit der 1.13er-Version von vor ca. 5 Tagen, wenn die angesprochenen Änderungen also schon länger her sind, dann habe ich schon die passende Version (denke ich).

LG
Lutz
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.03.2011, 16:55:44

Hi,

na immerhin bist du wieder erfolgreich zu Hause angekommen. :)

Aber zurück zum Thema: Ich habe gestern noch soweit rausgefunden, dass es offensichtlich keine Exception, sondern ein Error ist, der da angezeigt wird (also statt des Exception-Handlers wird der Error-Handler aktiviert).

In der Version 1.13 habe ich versucht, viele Dinge auf Exceptions umzustellen. Wenn dieses hier nicht gegeben ist, sollten wir uns das nochmal ansehen. Was rufst du hier genau auf? Wenn ich das lokal nachvollziehen kann, werde ich einen entsprechende Änderung vornehmen, damit du mit Exceptions arbeiten kannst (ist ja ohnehin mittelfristiges Ziel).

Das Problem wird das Gleiche bleiben: Eine Fehlermeldung wegen falscher Zugangsdaten (wenn diese halt falsch sind). Ich muss also so oder so irgendwie verhindern, dass diese Daten ausgegeben werden...

Korrekt. Du musst die Möglochkeit erhalten, die Exception abfangen zu können. Im Code habe ich gerade gesehen, dass der Bug 547 noch nicht für alle Fälle im MySQLiHandler abgefangen wurden. Potentiell kann dieser auch noch in den Methoden

  • __connect()
  • executeStatement()
auftreten. Nach einem kurzen Test ist es auch so, dass in real_connect()-Methode ein Error getriggert wird und sich das mit dem aktuellen Code nicht zu einer Exception auswirkt. Ich bau das mal um und meld mich wieder.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.03.2011, 17:05:41

Hallo Lutz,

ich habe mir die PHP-API nochmal genauer angesehen und hier haben wir nur die Möglichkeit den Fehler zu unterdrücken und statt dessen nur eine Exception zu werfen. Das war bereits vorbereitet, im Code braucht es nur ein unschönes "@" bei den Calls. Mit Commit #1237 im 1.14er-Branch ist das nun behoben. ZIP kannst du hier hier herunterladen.
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Catchen von DB-Exceptions?!

Beitrag von MrNiceGuy » 06.03.2011, 17:08:15

Ja, genau das real_connect() macht den Fehler. Im Grunde rufe ich nur den ConnectionManager auf und frage eine Connection ab:

Code: Alles auswählen

$oConnection = $oConnectionManager->getConnection ('cms_db');


Die Konfiguration dafür besteht, enthält aber halt zu Testzwecken einen Fehler. Entsprechend kommt dann die Fehlermeldung von real_connect():

Code: Alles auswählen

Error!
Error-ID: c9f1b7533ca3be78bf289c9494c4eea9
Message: mysqli::real_connect(): (28000/1045): Access denied for user 'root'@'localhost' (using password: YES)
Number: 2
File: /volume1/web/cms.mng/apf/core/database/MySQLiHandler.php
Line: 60
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Catchen von DB-Exceptions?!

Beitrag von MrNiceGuy » 06.03.2011, 17:09:39

Ihhhhh! Ein "@" im Code :cry: Gibt es keine andere Möglichkeit? Ich meine der Fehler wird ja durch den ErrorHandler gejagt, wäre hier ein Ansatz nicht schöner, als das "@"?
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.03.2011, 17:16:12

Leider nicht. Die PHP-API ist an dieser Stelle nicht für Exceptions ausgelegt. Damit haben wir nur die Möglichkeit im APF den Error zu unterdrücken und eine gemäß des ConnectionManager saubere DatabaseHandlerException zu werfen. Trotz des unschönen "@"'s halte ich das trotzdem für eine gute Lösung.

ErrorHandler und ExceptionHandler sollten ja konzeptuell nur für allgemeine Fehler und Exceptions verwendet werden. Alles, was du im Code behandeln möchtest, sollte auch behandelbar sein. Hierzu zählen für mich Datenbank-Zugriffsfehler definitiv. Ob ich im MySQLiHandler nun ein Error oder eine Exception fliegt, du hast immer noch die Möglichkeit das nicht zu behandeln, dann landet es ja im ExceptionHandler. Für deinen Fall also gut, für den allgemeinen Fall aber nicht schlecht. Einverstanden?
Viele Grüße,
Christian

Benutzeravatar
MrNiceGuy
Beiträge: 749
Registriert: 03.02.2009, 16:49:42
Wohnort: Nienburg / Weser

Re: Catchen von DB-Exceptions?!

Beitrag von MrNiceGuy » 06.03.2011, 17:19:40

OK, da ich mich noch zu wenig mit dieser Thematik beschäftigt habe, um eine andere Lösung vorschlagen zu können und ich davon ausgehe, dass du weißt, wovon du sprichst, bleibt wohl keine andere Möglichkeit. Schade, irgendwie bleibt so ein fader Beigeschmack nach dem Motto "Umgangen statt gelöst" :(
There are only 10 Types of people in the world:
Those who understand binary and those who don't.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.03.2011, 17:50:14

Der Beigeschmack bleibt, aber du kannst wenigstens auf Basis der APF-API sauber arbeiten. :)
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Catchen von DB-Exceptions?!

Beitrag von Well » 04.04.2011, 19:45:54

Ums mal eingebracht zu haben: Der Operator "@" unterdrückt leider aber auch Fehler wie
Fatal error: Call to undefined function mysql_connect() in /var/www/1.14/core/database/MySQLxHandler.php on line 63

wodurch das Skript komplett abgebrochen wird und nichts als eine leere Seite zum Vorschein bringt. Das ist so ein ziemlich langer Weg bis zum fehlendem Paket. :(

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 04.04.2011, 20:04:46

Hallo Well,

da hast du definitv Recht. Das Problem dabei ist jedoch, dass ich nicht für jeden Funktions-Aufruf ein function_exists() einbauen und das in eine Exception mappen kann. Man könnte höchstens im Konstruktor via extension_loaded prüfen und ggf. schon dann eine Exception feuern. Andererseits kannst du auch nicht jeden (Konfigurations-)Fehler abfangen...

Theoretisch solltest du aber eine Exception mit einem vernünftigen Stacktrace bekommen, oder? Dieser sagt zwar nicht direkt, was ihm fehlt, aber zumindest solltest du die Code-Stelle schnell finden.
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Catchen von DB-Exceptions?!

Beitrag von Well » 06.04.2011, 14:31:01

Theoretisch solltest du aber eine Exception mit einem vernünftigen Stacktrace bekommen, oder? Dieser sagt zwar nicht direkt, was ihm fehlt, aber zumindest solltest du die Code-Stelle schnell finden.

Das wäre toll. Im Moment wird aber, wie gesagt, nur das Skript abgebrochen und es erscheint gar keine Meldung - nur ein weißer Bildschirm.

Dass nicht überall geprüft werden kann, ob eine Funktion vorhanden ist, ist mir klar... Aber wäre es in diesem Fall nicht sinnvoll? Ein »@« kommt ja nicht oft vor...

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Catchen von DB-Exceptions?!

Beitrag von dr.e. » 06.04.2011, 18:13:50

An sich ist eine Prüfung schon sinnvoll, aber nicht im Kontext einer nicht vorhandenen Funktion. Das halte ich in der Tat nicht für eine Aufgabe des APF. :roll:
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Catchen von DB-Exceptions?!

Beitrag von Well » 30.03.2016, 03:27:02

Im Allgemeinen verstehe ich das.

In diesem Fall ist das APF aber wirklich komplett(!) schweigend gestorben, wenn die mysql-Extension nicht installiert war. Ist das nicht ein großes No-Go? Jetzt auch aus Sicht der Benutzerfreundlichkeit. Ich kenne kein anderes Framework, das so reagiert.

Ich hätte die Prüfung als Teil des "@"-Workarounds gesehen, nicht als neue Anforderung oder so. In Java fange ich doch auch kein Throwable, und lasse dann die Anwendung (und in einer Library ist das ja noch schlimmer) im Falle einer NoClassDefFound stillschweigend sterben.

Dazu war das letztendlich auch keine Funktion, die jede PHP Installation hat, sondern die aus einer Erweiterung stammte. Das APF hat derart also nicht reagiert, wenn eine einzelne Funktion gefehlt hat, sondern wenn eine benötigte Erweiterung gefehlt hat.
JPA terminiert meine Anwendung nicht ohne jeden Log, wenn der Provider im Classpath fehlt.

Ich kann deine Entscheidung noch immer nicht nachvollziehen.

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast