Melvin Cowznofski: PDO Exception in eigenem Namespace

Hallo,

ich hatte gestern das Problem, dass bei einem Verbindungsaufbau zu einer MySQL Datenbank mittels PDO keine Exceptions mehr abgefangen worden sind. Mit den richtigen Zugangsdaten wurde eine Verbindung mit der DB problemlos hergstellt, habe ich User, DB, Host oder Passwort absichtlich falsch geschrieben, dann kam nicht wie erwartet die Exception Message, sondern ein "Fatal error: Uncaught exception 'PDOException' with message ...".

Ich habe stundenlang versucht, die Ursache für diesen Fehler zu finden, bis ich endlich herausgefunden hatte, dass mein eigener Namespace dafür verantwortlich war. Ohne Angabe eines eigenen Namespaces kam die Exception Message dann nämlich wieder wie erwartet ohne der Fehlermeldung.

Bei einer weiteren Recherche fand ich dann nach langer Suche endlich heraus, dass man das Problem löst, in dem man statt einem try{} catch(PDOException $e){} einen try{} catch(\PDOException $e){} Block schreibt.

Nun ist mein Problem zwar gelöst, ich würde mir die Sache aber gerne noch erklären lassen hier.

Mir ist klar, dass ich, nachdem ich einen eigenen Namespace verwende, am Anfang der Seite gleich nach der Namensangabe ein use \PDO; schreibe, um anzugeben, dass die PDO Klasse nicht zu meinem eigenen Namespace gehört. Aber wieso verlangt dann die Exception Angabe auch nach einem Backslash? Ein try/catch Block ist doch was "Allgemeines", das hat doch mit dem Namespace nichts zu tun?!

PS: Bin ich zu blöd, um es zu finden oder gibt es im neuen Forum kein PHP Syntax Highlighting mehr?

Mit lieben Grüßen

Melvin Cowznofski

--
Melvin Cowznofski What – me worry?
  1. Tach,

    Mir ist klar, dass ich, nachdem ich einen eigenen Namespace verwende, am Anfang der Seite gleich nach der Namensangabe ein use \PDO; schreibe, um anzugeben, dass die PDO Klasse nicht zu meinem eigenen Namespace gehört. Aber wieso verlangt dann die Exception Angabe auch nach einem Backslash?

    weil die Klasse PDOException nicht zum Namespace PDO gehört sondern zum globalen Namespace. Ich habe keine Ahnung, warum das so ist (und hätte dann nicht der Compiler schon einen Fehler werfen müssen, weil er PDOException innerhalb deines Namespaces, sowie der mit use deklarierten Namespaces nicht finden konnte?), aber vielleicht sieht @Sven Rautenberg oder ein anderer PHP-Entwickler das hier ja noch und kann das erklären.

    PS: Bin ich zu blöd, um es zu finden oder gibt es im neuen Forum kein PHP Syntax Highlighting mehr?

    Doch gibt es:

    use PDO;
    

    mfg
    Woodfighter

    1. Tach!

      weil die Klasse PDOException nicht zum Namespace PDO gehört sondern zum globalen Namespace.

      Es gibt keinen Namespace PDO. PDO ist eine Klasse im globalen Namespace. use \PDO holt die Klasse in den aktuellen Namespace.

      Ich habe keine Ahnung, warum das so ist (und hätte dann nicht der Compiler schon einen Fehler werfen müssen, weil er PDOException innerhalb deines Namespaces, sowie der mit use deklarierten Namespaces nicht finden konnte?),

      Der PHP-Compiler ist nicht für das Auflösen von Namen zuständig. Bei einer dynamischen Sprache ergeben sich die Auflösungsmöglichkeiten unter Umständen erst im Verlaufe des Scripts. Das kann nicht schon zur Compile-Zeit erfolgen.

      dedlfix.

      1. Tach,

        Es gibt keinen Namespace PDO. PDO ist eine Klasse im globalen Namespace. use \PDO holt die Klasse in den aktuellen Namespace.

        ah, so ergibt das mehr Sinn.

        Der PHP-Compiler ist nicht für das Auflösen von Namen zuständig. Bei einer dynamischen Sprache ergeben sich die Auflösungsmöglichkeiten unter Umständen erst im Verlaufe des Scripts. Das kann nicht schon zur Compile-Zeit erfolgen.

        Ok, dann arbeitet der PHP-Compiler hier deutlich anders als ich das von Java gewohnt bin, da wird nicht erst zur Runtime festgestellt, ob die Klassen etc. zugänglich sind.

        mfg
        Woodfighter

        1. Tach!

          Der PHP-Compiler ist nicht für das Auflösen von Namen zuständig. Bei einer dynamischen Sprache ergeben sich die Auflösungsmöglichkeiten unter Umständen erst im Verlaufe des Scripts. Das kann nicht schon zur Compile-Zeit erfolgen.

          Ok, dann arbeitet der PHP-Compiler hier deutlich anders als ich das von Java gewohnt bin, da wird nicht erst zur Runtime festgestellt, ob die Klassen etc. zugänglich sind.

          Wir haben es ja bei PHP auch nicht mit einem kompilierenden System im klassischen Sinne zu tun. Man könnte es im Prinzip als interpretatives System betrachten, und das wäre nicht ganz verkehrt. Der Compiler ist hier nur ein Bytecode-Compiler. Da man aber zur Laufzeit mit include und Co. (und auch mit eval()) Code nachladen kann, und das auch bedingt, und auch solche Konstrukte wie variable Variablen hat, kann man vor dem Start kein vollständiges Kompilat erstellen, und damit auch nicht wissen, was eingeladen werden wird und was nicht, was zur Verfügung steht und was nicht. Somit ist der Compiler nicht in der Lage, einen Find-ich-nicht-Fehler zu erzeugen.

          dedlfix.

          1. Tach,

            Ok, dann arbeitet der PHP-Compiler hier deutlich anders als ich das von Java gewohnt bin, da wird nicht erst zur Runtime festgestellt, ob die Klassen etc. zugänglich sind.

            Wir haben es ja bei PHP auch nicht mit einem kompilierenden System im klassischen Sinne zu tun. Man könnte es im Prinzip als interpretatives System betrachten, und das wäre nicht ganz verkehrt. Der Compiler ist hier nur ein Bytecode-Compiler. Da man aber zur Laufzeit mit include und Co. (und auch mit eval()) Code nachladen kann, und das auch bedingt, und auch solche Konstrukte wie variable Variablen hat, kann man vor dem Start kein vollständiges Kompilat erstellen, und damit auch nicht wissen, was eingeladen werden wird und was nicht, was zur Verfügung steht und was nicht. Somit ist der Compiler nicht in der Lage, einen Find-ich-nicht-Fehler zu erzeugen.

            das ist ja bei Java erstmal nicht anders, ich kann z.B. mit Class.forName("gibtsnicht") eine Klasse zur Laufzeit laden, darauf reagiert dann der Compiler auch nicht, sondern ich muss mich selber um ClassNotFoundException etc. kümmern. Aber für alles, was zur Compile-Zeit feststeht, wird die Anwesenheit geprüft.

            Und eigentlich sollte ich weniger verwundert darüber sein, Python macht es genauso wie PHP.

            mfg
            Woodfighter

            1. Hi,

              das ist ja bei Java erstmal nicht anders, ich kann z.B. mit Class.forName("gibtsnicht") eine Klasse zur Laufzeit laden, darauf reagiert dann der Compiler auch nicht, sondern ich muss mich selber um ClassNotFoundException etc. kümmern. Aber für alles, was zur Compile-Zeit feststeht, wird die Anwesenheit

              zur Compile-Zeit

              geprüft.

              Ob die Klasse zur Laufzeit zur Verfügung stehen wird, kann der Java-Compiler natürlich auch nicht feststellen.

              cu,
              Andreas a/k/a MudGuard

              1. Tach,

                Ob die Klasse zur Laufzeit zur Verfügung stehen wird, kann der Java-Compiler natürlich auch nicht feststellen.

                ja natürlich

                mfg
                Woodfighter

  2. Tach!

    Mir ist klar, dass ich, nachdem ich einen eigenen Namespace verwende, am Anfang der Seite gleich nach der Namensangabe ein use \PDO; schreibe, um anzugeben, dass die PDO Klasse nicht zu meinem eigenen Namespace gehört.

    Genauer gesagt, weist du hier an, dass PDO aus dem globalen Namespace genommen werden soll. Die ausführliche Schreibweise zeigt das deutlicher:

    use \PDO as PDO;
    

    Die globale Klasse PDO wird als PDO in deinen Namespace importiert.

    Aber wieso verlangt dann die Exception Angabe auch nach einem Backslash?

    Weil das auch eine Klasse ist, die nicht in deinem Namespace zu finden ist, sondern ebenfalls im globalen.

    Ein try/catch Block ist doch was "Allgemeines", das hat doch mit dem Namespace nichts zu tun?!

    Nicht? Der Code steht doch in einem von dir angelegten Namespace. Also muss er sich auch an üblichen Regeln halten.

    PS: Bin ich zu blöd, um es zu finden oder gibt es im neuen Forum kein PHP Syntax Highlighting mehr?

    Nimm das Symbol </> aus dem Menü und dann wirst du gefragt.

    dedlfix.

    1. Hallo dedlfix,

      Aber wieso verlangt dann die Exception Angabe auch nach einem Backslash?

      Weil das auch eine Klasse ist, die nicht in deinem Namespace zu finden ist, sondern ebenfalls im globalen.

      OK, das war mir nicht bewusst, dass es sich bei der PDOException ebenfalls um eine Klasse handelt. Ich sah das als einen "normalen PHP Befehl" an. Aber somit erklärt das, wieso es sich in einem eigenen Namespace wehrt. Mich wundert nur, dass die eigentliche Fehlermeldung in diesem Errorgewulst trotzdem enthalten war.

      Ein try/catch Block ist doch was "Allgemeines", das hat doch mit dem Namespace nichts zu tun?!

      Nicht? Der Code steht doch in einem von dir angelegten Namespace. Also muss er sich auch an üblichen Regeln halten.

      Das war aus der falschen Sichtweise heraus, es handele sich um einen "normalen PHP Befehl".

      Mit anderen Worten ... dann könnte ich also, wenn ich mehrere PDO try/catch Blöcke in einer Ressource habe, es mir sparen, jedesmal den Backslash zu setzen und statt dessen so wie bei

      use \PDO as PDO;
      

      ein

      use \PDOException as PDOException
      

      zu setzen?

      Nimm das Symbol </> aus dem Menü und dann wirst du gefragt.

      Danke für die Bedienungshilfe, Du siehst, es hat funktioniert. Ich finde es nur schade, dass das jetzt nur mehr als Blockelement möglich ist und nicht wie früher auch inline mitten im Text.

      Mit lieben Grüßen

      Melvin Cowznofski

      --
      Melvin Cowznofski What – me worry?
      1. Tach!

        Mich wundert nur, dass die eigentliche Fehlermeldung in diesem Errorgewulst trotzdem enthalten war.

        Da hat der globale Exceptionhandler zugeschlagen, der immer anspringt, wenn eine Exception nicht gefangen wird.

        Mit anderen Worten ... dann könnte ich also, wenn ich mehrere PDO try/catch Blöcke in einer Ressource habe, es mir sparen, jedesmal den Backslash zu setzen

        Ja, im Prinzip schon. Aber wieviele Backslashes sparst du und wieviel Zeichen musst du für die use-Anweisung zusätzlich notieren?

        Ich finde es nur schade, dass das jetzt nur mehr als Blockelement möglich ist und nicht wie früher auch inline mitten im Text.

        Inline geht mit `Backticks`. Und in einer erweiterten Syntax auch mit Angabe des Sprachnamens, was ist aber im Verhältnis zum Nutzen zu umständlich ist.

        dedlfix.

        1. Hallo dedlfix,

          dann danke vielmals für die Behandlung meiner Anfrage und die verständlichen Antworten! Meine Frage ist somit beantwortet.

          Mit lieben Grüßen

          Melvin Cowznofski

          --
          Melvin Cowznofski What – me worry?